У всего есть свой потенциал, раскрытие которого возможно благодаря интеллектуальной работе некоторого юнита. Конечно же все не раскрывается в одночасье и юниту требуется время, чтобы разобраться что к чему, это в свою очередь переростает в опыт, а там глядишь и почетная грамота со статусом MVP. Если же серьезно, работа исследователя основана на одном лишь энтузиазме, а опыт — бесценен.
Каждый охотник желает знать...
До появления PowerShell каких только ухищрений не предпринималось различными юнитами, дабы заставить командную строку заиграть цветами радуги. Впрочем, появление PowerShell мало что изменило, по крайней мере в сознании вышеобозначенных юнитов, ибо несмотря на наличие возможности вывода цветных сообщений, например:
Write-Host ('0x{0:X}' -f 12) -ForegroundColor green
это не было способно кого-то удивить. А как на счет чего-то более замысловатого? Скажем, разлиновка при выводе данных некоторой команды.
$line = {
param(
[Int32]$x, #координаты по оси X
[Int32]$y, #координаты по оси Y
[String]$msg = $null, #вывести сообщение или нет
[ConsoleColor]$fc = 'White', #цвет текста
[ConsoleColor]$bc = 'Black' #цвет фона
)
#расположение окна, а также его размер
$pos = ($raw = $host.UI.RawUI).WindowPosition
$con = $raw.WindowSize
#задаем координаты линии
$pos.X += $x
$pos.Y += $y
#выравнивание относительно длины текста
switch ([String]::IsNullOrEmpty($msg)) {
$true { $msg = "$([Char]32)" * $con.Width }
$false { $msg += "$([Char]32)" * ($con.Width - $msg.Length) }
}
$row = $raw.NewBufferCellArray(@($msg), $fc, $bc)
#отрисовка
$raw.SetBufferContents($pos, $row)
}
($$ = Get-ChildItem) | ForEach-Object {
$i = 0
[Console]::SetCursorPosition(0, $$.Count)
}{
if ($i % 2 -eq 0) {
&$line 0 $i $_.FullName 'Black' 'Magenta'
}
else { &$line 0 $i $_.FullName 'Yellow' 'Black'}
$i++
}
Как вам такие коврижки? Причем рисованием линий дело вовсе не ограничивается, так как при наличии времени и должного стимула можно вполне выводить в хосте более сложные с точки зрения геометрии объекты.
Зе титле...
Главное отличие PowerShell от обычной командной строки — можно вертеть заголовком хоста в угоду своим нуждам. Так, еще с PowerShell v2 памятен простой трюк мониторинга времени работы с хостом.
[void]([PowerShell]::Create()).AddScript({
$st = (Get-Process -Id $PID).StartTime #время запуска хоста
while ($true) { #непрерывно обновляем заголовок
[Console]::Title = '{0}.{1:D2}:{2:D2}:{3:D2}' -f (
$$ = [DateTime]::Now - $st
).Days, $$.Hours, $$.Minutes, $$.Seconds
Start-Sleep -Seconds 1
}
}).BeginInvoke()
less дремучий
Имеющие опыт работы в Bash или Cygwin знают о такой команде, как less, примечательной главным образом своей функцией поиска по тексту. В Windows такой команды нет, но есть Alt+Space->Изменить->Найти… но! Дабы не играть пальцами в «Твист», можно поступить следующим образом.
$find = {
#хэндл текущего хоста
$href = New-Object Runtime.InteropServices.HandleRef(
(New-Object IntPtr),
[PSObject].Assembly.GetType(
'System.Management.Automation.ConsoleVisibility'
).GetMethod(
'GetConsoleWindow', [Reflection.BindingFlags]40
).Invoke($null, @())
)
#шлем хосту сообщение 0xfff4 - Найти...
[void][Regex].Assembly.GetType(
'Microsoft.Win32.UnsafeNativeMethods'
).GetMethod('SendMessage').Invoke($null, @(
[Runtime.InteropServices.HandleRef]$href,
0x0111, [IntPtr]0xfff4, [IntPtr]::Zero
))
}
Если код выше был набит в самом хосте, можно задать макрос:
doskey /exename=powershell.exe find=`&$find
Так как макрос имеет более высокий приоритет перед командами, вместо штатной консольной утилиты find.exe будет вызван все тот же пункт меню «Найти...»; можно то же поместить в профиль пользователя (man about_Profiles). Стоит заметить — меняя значение 0xfff4, можно вызывать и прочие пункты меню.
0xfff1 - Вставить
0xfff2 - Пометить
0xfff3 - Прокрутить
0xfff5 - Выделить все
Напоследок...
… пример того, как можно узнать текущий уровень заряда батареи ноутбука в обход WMI.
Add-Type -AssemblyName System.Windows.Forms
[Windows.Forms.PowerStatus].GetConstructor(
[Reflection.BindingFlags]36, $null, [Type[]]@(), $null
).Invoke($null)
комментарии (9)