Делимся своими профилями PowerShell

Решил присоединиться к благородному движению по публикации профилей PowerShell. ;)

Собственно, вот он, мой профиль:

# Еще один алиас для get-help (мне так удобнее)
Set-Alias gh get-Help
#from PSCX
$IsElevated=$false
foreach ($sid in [Security.Principal.WindowsIdentity]::GetCurrent().Groups) {
    if ($sid.Translate([Security.Principal.SecurityIdentifier]).IsWellKnown([Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)) {
        $IsElevated=$true
    }
}
# Формируем приглашение командной строки и заголовок окна PoSh
Function Prompt  {
    #Поменяем заголовок окна
    (Get-Host).UI.RawUI.WindowTitle="PS # $env:computername # $env:userdomain\$env:username  #  $(Get-Location)"
    #Определяем значение переменной $PromptStr, которая будет содержать приглашение командной строки
    $HistoryCount=(Get-History -Count 1).Id+1
    if ($NestedPromptLevel) {$PromtStr="PS($HistoryCount)>nested($NestedPromptLevel)>"} else {$PromtStr="PS($HistoryCount)>"}
    #Если мы работаем с правами лок. админа, то текст приглашения командной строки - красный
    #иначе - зеленый
    if ($isElevated) {$PromptColor = "Red"} else {$PromptColor = "Green"}
    #Выводим на экран приглашение командной строки
    Write-Host $PromtStr -ForegroundColor $PromptColor -NoNewline
    #
    " "
    #
    ##############################################################################################
    #### Синхронизируем текущую папку хостового приложения (PowerShell.exe) и 
    #### текущую папку "внутри" хостового приложения, 
    #### которая может быть установлена при помощи set-location
    #### http://xaegr.wordpress.com/2009/05/14/prompt/ 
    #
    [Environment]::CurrentDirectory=(Get-Location -PSProvider FileSystem).ProviderPath
}
#
#############################################################################################
"Добавление всех зарегистрированных оснасток..."
#
get-pssnapin -registered | add-pssnapin -passthru -ErrorAction SilentlyContinue
"... и модулей...`n"
Get-Module -ListAvailable| Import-Module -PassThru -ErrorAction SilentlyContinue
"...готово`n"
#
#
##############################################################################################
#### Установим кодовую страницу передачи данных по конвейеру
#### для native applicatition (не командлетов, таких как findstr, dsquery, etc.)
#### http://blogs.msdn.com/powershell/archive/2006/12/11/outputencoding-to-the-rescue.aspx ###
#
$OutputEncoding = [Console]::OutputEncoding
#

Ничего оригинального, но мне нравится ;)

Поясню чуть более подробно содержимое некоторых частей моего профиля.

Функция prompt позволяет настроить вид приглашения командной строки. Настраивать prompt можно было и в cmd.exe при помощи (вы не поверите ;)) команды prompt. Но в PowerShell появилась возможность влиять не только на приглашение командной строки, но и на само консольное окно PowerShell.

IMHO, с тех пор, как имена файлов и папок стали длинными, promt (приглашение командной строки) на экране стало занимать слишком много места, загромождая экран и мешая копированию введенных команд из одного окна в другое. Но в cmd.exe с этим ничего поделать было нельзя. Вернее из 2х зол: отображать очень длинный путь к текущей папке, либо не отображать его вообще, я, естественно, выбирал первое. В PowerShell же я решил вынести информацию о текущей папке, добавив к ней информацию о текущем пользователе, в заголовок консольного окна, тем самым убив 2х зайцев:

  • расчистил приглашение командной строки,
  • избавил себя от необходимости выполнять какую-либо команду (например set, whoami, gpresult, etc) для того, чтобы «вспомнить»: от имени какого пользователя была запущена эта конкретная консоль PowerShell?

Для тех кто, как и я, привык использовать внешние команды ОС Windows в командной строке, и строить из таких команд конвейер, неприятным сюрпризом будет то, что в консоли PowerShell такие конвейеры почему-то «не работают». На самом деле эти конвейеры по-прежнему работоспособны, но (при передаче данных по конвейеру к внешней команде ОС Windows)  PowerShell использует кодировку, указанную в переменной $OutputEncoding. По-умолчанию эта переменная всегда имеет следующее содержимое:

PS > $OutputEncoding

IsSingleByte : True

BodyName : us-ascii

EncodingName : US-ASCII

HeaderName : us-ascii

WebName : us-ascii

WindowsCodePage : 1252

IsBrowserDisplay : False

IsBrowserSave : False

IsMailNewsDisplay : True

IsMailNewsSave : True

EncoderFallback : System.Text.EncoderReplacementFallback

DecoderFallback : System.Text.DecoderReplacementFallback

IsReadOnly : True

CodePage : 20127

Как вы понимаете, с такими настройками текстовая информация, если она содержит текст в кодировке, отличной от заданной в переменной $OutputEncoding, будет искажена при передаче по конвейеру, и, в результате, конвейер команд отработает неправильно. Чтобы этого не происходило, необходимо задать правильную кодировку в переменной $OutputEncoding. Для этого используется следующая строка:

$OutputEncoding = [Console]::OutputEncoding

В результате содержимое переменной OutputEncoding будет иметь следующий вид:

PS > $outputEncoding

IsSingleByte : True

BodyName : cp866

EncodingName : Кириллица (DOS)

HeaderName : cp866

WebName : cp866

WindowsCodePage : 1251

IsBrowserDisplay : True

IsBrowserSave : True

IsMailNewsDisplay : False

IsMailNewsSave : False

EncoderFallback : System.Text.InternalEncoderBestFitFallback

DecoderFallback : System.Text.InternalDecoderBestFitFallback

IsReadOnly : True

CodePage : 866

А конвейер native’ных команд, например dsquery user | dsget user –samid будет работать, даже если DN ваших пользователей содержит кириллицу.

Об этом я прочитал здесь: http://blogs.msdn.com/powershell/archive/2006/12/11/outputencoding-to-the-rescue.aspx, спасибо автору (авторам?) блога за пояснения.

PS Да, чуть не забыл, результат работы профиля см. на картинке ниже

UPD [20101201] Привел опубликованный профиль в соответствие со своим текущим профилем:

Соблазнился и позаимствовал у Васи кусок кода (который он, в свою очередь, позаимствовал у PSCX), отрисовывающий приглашение командной строки разным цветом.  Если есть права лок. админа, то приглашение будет красным, нет – зеленым.

Опять-таки у Васи утащил идею с нумерацией приглашений командной строки. Теперь каждая строка имеет номер равный номеру команды в истории команд, возвращаемой командлетом get-history.

UPD [20160907] Добавил в профиль функцию конвертирования текста из одной кодировки в другую. Эта функцию приходится использовать вместе с PowerShell remoting. Дело в том, что при выполнении нативных команд на удаленном компьютере вместо внятного локализованного текста мы получим “крокозябры”. Эти “крокозябры” можно привести в читабельный вид при помощи этой функции, например: Invoke-Command -ComputerName RemoteCompName -Command {powercfg -l}| ConvertTo-Encoding cp866 windows-1251

function ConvertTo-Encoding ([string]$From, [string]$To){
    Begin{
        $encFrom = [System.Text.Encoding]::GetEncoding($from)
        $encTo = [System.Text.Encoding]::GetEncoding($to)
    }
    Process{
        $bytes = $encTo.GetBytes($_)
        #$bytes = [System.Text.Encoding]::Convert($encFrom, $encTo, $bytes)
        #$encTo.GetString($bytes)
        $encFrom.GetString($bytes)
    }
}

One Comment

  1. Pingback: Копирование больших файлов при помощи PowerShell (с использованием службы BITS) - ShS's Blog

Leave a Reply

Your email address will not be published. Required fields are marked *

Notify me of followup comments via e-mail. You can also subscribe without commenting.