У всего есть свой потенциал, раскрытие которого возможно благодаря интеллектуальной работе некоторого юнита. Конечно же все не раскрывается в одночасье и юниту требуется время, чтобы разобраться что к чему, это в свою очередь переростает в опыт, а там глядишь и почетная грамота со статусом 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)


  1. BlackMetal
    30.06.2016 10:03
    -7

    Что-то резко увеличилось кл-во постов про PowerShell, совпадение, да?
    По теме: это какой-то новорождённый сынок Баша, судя по функционалу и костылям в стиле Microsoft.


    1. ad1Dima
      30.06.2016 10:14
      +3

      10 лет, не многовато-ли для новорожденного?


      1. BlackMetal
        30.06.2016 23:43
        -2

        Т.е. за 10 лет нельзя довести проект до нормального состояния?


        1. ad1Dima
          01.07.2016 04:44
          +1

          Кроме вбросов, есть какие-то критерии нормальности?


          1. BlackMetal
            01.07.2016 10:46
            -1

            Вброс тут — сама статья. Критерии есть, конечно. Расширяемость, функциональность, открытость, отсутствие костылей.


            1. ad1Dima
              01.07.2016 10:59
              +1

              Расширяемость
              Функциональность — вся мощь .NET
              Открытость — ок запишем в минусы.
              Отсутствие костылей — субъективный критерий


              1. BlackMetal
                02.07.2016 01:28

                Это и называется мощью? Спасибо, немного пробило на смех.
                Да нет, не субъективный.


    1. potan
      30.06.2016 20:56
      +2

      Сам линуксоид-программист, вынужденный по работе использовать винды утвержда, что powershell гораздо удобнее, чем bash. Естественно, при использовании нормального терминала (я использую ConEmu). Хотя есть мелкие неудобства в комплетишеном.


      1. p0z
        02.07.2016 11:56

        Для правки скриптов использую PowerGUI Script Editor. Да, не консоль, но дествительно удобно.