Привычные вещи отнюдь не статичны как о них положено думать, и если на них посмотреть под иным углом, причем не обязательно с высоким градусом и вызывающим похмелье, можно открыть для себя нечто новое, способное во многом повысить эффективность работы.
Если проводить аналогии, профили PowerShell — те же конфигурационные файлы терминалов *nix, основное назначение которых хранить пользовательские настройки. Более подродно о профилях можно почитать во встроенном руководстве:
PS C:\> man about_Profiles
Совершенно очевидно, что пихать в профиль все что ни поподя не следует — чем больше вес файла, тем менее скорость загрузки хоста, если конечно не был указан параметр /noprofile при вызове последнего. Обычно профили применяются для упреждения неоднозначностей (о них чуть позже), настройки окружения и определения часто используемых функций. Попробуем пояснить это на примере.
PS C:\> ni -Type File -Path $Profile -Force PS C:\> vim $Profile #vim - сугубо личное предпочтение
Было бы неплохо иметь постоянно доступ к ускорителям типов.
if (($ta = [PSObject].Assembly.GetType( 'System.Management.Automation.TypeAccelerators' ))::Get.Keys -notcontains 'accelerators') { $ta::Add('accelerators', $ta) }
Для того, чтобы изменения вступили в силу, требуется перезапустить хост.
PS C:\> ii (ls $env:allusersprofile -r -ea 0).Where({$_.Name -match 'shell.lnk'}).FullName;kill $pid ... PS C:\> [accelerators]::Get Key Value --- ----- Alias System.Management.Automation.AliasAttribute AllowEmptyCollection System.Management.Automation.AllowEmptyCollectionAttribute AllowEmptyString System.Management.Automation.AllowEmptyStringAttribute AllowNull System.Management.Automation.AllowNullAttribute array System.Array bool System.Boolean byte System.Byte char System.Char CmdletBinding System.Management.Automation.CmdletBindingAttribute datetime System.DateTime ...
Ранее упомяналось о неких неоднозначностях, самая пора к ним вернуться. Дело в том, что от использования переменных env: следует отказаться по причине возможности их изменения.
PS C:\> gc env:allusersprofile C:\ProgramData PS C:\> $old = gc env:allusersprofile PS C:\> sc env:allusersprofile C:\ PS C:\> gc env:allusersprofile C:\ PS C:\> sc env:allusersprofile $old PS C:\> gc env:allusersprofile C:\ProgramData
Иными словами перезапуск хоста способом выше без предварительной проверки переменной allusersprofile — не самая лучшая идея, и, если в том возникает необходимость, лучше использовать переменные окружения определенные в Environment+SpecialFolder или просто предопределить некоторые переменные env: в виде констант.
Так как Корзина используется некоторыми как пункт промежуточного хранения файлов, почему бы не упростить себе задачу и в этом случае?!
Set-Content function:trash { param( [Parameter(Mandatory=$true)] [ValidateScript({Test-Path $_})] [String]$Path ) (New-Object -ComObject Shell.Application).NameSpace(0xA).MoveHere( (Convert-Path $Path) ) }
В итоге помещать файлы в Корзину станет проще:
PS C:\> trash E:\doc\foo
Требуется возможностью перевода незнакомых слов? Денег на покупку дорогостоящих приложений у нас нет, поэтому будем использовать онлайн-переводчик, а точнее — Яндекс.Перевод, благо у того вменяемое API, да и качество переводов неплохое. Устанавливаем API-ключ.
PS C:\> $key = '...' #API-ключ PS C:\> $bin = "$([Environment]::GetFolderPath('UserProfile'))\yatrans.bin" PS C:\> Add-Type -AssemblyName System.Security PS C:\> [IO.File]::WriteAllBytes( >> $bin, >> [Security.Cryptography.ProtectedData]::Protect( >> [Text.Encoding]::Unicode.GetBytes($key), >> $null, >> [Security.Cryptography.DataProtectionScope]::CurrentUser >> )) >> PS C:\> attrib +h $bin
Ключ установили, теперь можно приступать к чтению документации API. Если же совсем невтерпеж, то в самом простом варианте, функция перевода может выглядеть так.
function Get-Translation { param( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [String]$Data ) begin { Add-Type -AssemblyName System.Security # декодирование ключа if (Test-Path ($key = "$([Environment]::GetFolderPath('UserProfile'))\yatrans.bin")) { $key = [Text.Encoding]::Unicode.GetString( [Security.Cryptography.ProtectedData]::Unprotect( [IO.File]::ReadAllBytes($key), $null, [Security.Cryptography.DataProtectionScope]::CurrentUser ) ) } else { throw 'API-ключ Яндекс.Перевод не найден.' } # url-root $url = 'https://translate.yandex.net/api/v1.5/tr/' # определение языка оригинала $detect = "$($url)detect?key=$key&text=" # перевод $transl = "$($url)translate?key=$key&text=%t&lang=%l-ru&format=plain" # user agent $usr = 'Mozilla/5.0 (Windows NT 6.3; rv:37.0.1) Gecko/20100101 Firefox/37.0.1' } process { # для перевода текстовых файлов $Data = if (Test-Path $Data) { gc $Data } else { $Data } $res = [xml](wget "$detect$Data" -DisableKeepAlive -UseBasicParsing -UserAgent $usr).Content if ($res.DetectedLang.code -ne 200) { throw 'Невозможно определить язык.' } $transl = $transl -replace '%t', $Data $transl = $transl -replace '%l', $res.DetectedLang.lang $res = [xml](wget $transl -DisableKeepAlive -UseBasicParsing -UserAgent $usr).Content if ($res.Translation.code -ne 200) { throw 'Невозможно перевести текст.' } $res.Translation.text } }
Функция в действии:
PS C:\> Get-Translation 'Die Zeit ist auf!' - Время! PS C:\> vim foo Hey, teacher! Leave this kids alone! ... PS C:\> Get-Translation foo Эй, учитель! Оставить детей в покое! PS C:\> ri foo PS C:\>
К слову, Яндекс предоставляет возможность узнать свой публичный IP — также может сгодиться в хозяйстве:
$par = @{ Uri = 'http://ipv4.internet.yandex.ru/internet/api/v0/ip' DisableKeepAlive = $true UseBasicParsing = $true UserAgent = 'Mozilla/5.0 (Windows NT 6.3; rv:37.0.1) Gecko/20100101 Firefox/37.0.1' } (wget @par).Content -replace [Char]34, ''
Все, что не планируется использовать в повседневной работе, лучше выносить в отдельные модули.
ссылка на оригинал статьи http://habrahabr.ru/post/255973/
Добавить комментарий