октябрь 2016
Том 31 Номер 10
Главное в .NET - Windows PowerShell продолжает меняться в лучшую сторону
Марк Михейлис | октябрь 2016
В качестве отхода от фокуса на .NET Core сегодня я намерен уделить основное внимание ряду новых средств, значительно повышающих мощь Windows PowerShell. Для меня самые важные усовершенствования лежат в области кросс-платформенной поддержки. Да, представьте, PowerShell теперь работает в Linux. Более того, его исходный код открыт и выложен на GitHub (github.com/PowerShell/PowerShell), чтобы сообщество в целом могло приступить к расширению ее возможностей. Потрясающе!
Но самые недавние объявления не отражают всю полноту новшеств. PowerShell 5.0 была выпущена еще в феврале и включает новую и улучшенную поддержку объявлений классов и перечислений, обнаружения модулей и скриптов, управления упаковкой и установкой, доступа к конечным точкам OData, улучшенные средства протоколирования и др. В этой статье я дам обзор каждого из этих средств и предоставлю примеры.
PowerShell становится кросс-платформенной
Для начала взгляните на следующий командный скрипт, который устанавливает PowerShell в Ubuntu 14.04 с Windows PowerShell Host, и экранный снимок сеанса выполнения из Windows Bash на рис. 1. (Для тех, кто не знаком с Bash, выполняющим Ubuntu в Windows 10 Anniversary Update, см. врезку «Установка Bash в Windows 10».)
wget -O powershell.deb https://github.com/PowerShell/
PowerShell/releases/download/v6.0.0-alpha.9/
powershell_6.0.0-alpha.9-1ubuntu1.14.04.1_amd64.deb
sudo apt-get install libunwind8 libicu52
sudo dpkg -i powershell.deb
powershell
Рис. 1. Установка и запуск Windows PowerShell в Ubuntu 14.04 из Bash в Windows
Заметьте, что командный скрипт предназначен специально для Ubuntu 14.04. Для других платформ URL пакета deb и версии обязательных компонентов будут отличаться. Инструкции для конкретной платформы см. по ссылке bit.ly/2bjAJ3H.
Много лет назад Джеффри Сноувер (Jeffrey Snover) опубликовал твит о том, что через некоторое время PowerShell мог бы появиться в Linux, но этот процесс занял гораздо дольше, и за весь период было так мало сообщений о прогрессе, что даже сегодня, когда я использую PowerShell, я не перестаю удивляться. Я запускаю Bash поверх Ubuntu, выполняемой в Windows (без применения какой-либо технологии виртуализации), и (предполагая, что я не хочу устанавливать PowerShell прямо в тот же экземпляр Bash) использую SSH для подключения к удаленному сеансу Bash, где можно установить PowerShell и передавать .NET-объекты между командами внутри оболочки Bash.
Если бы еще несколько лет назад я предположил, что такое будет возможным, сомневаюсь, что кто-нибудь поверил бы мне.
Установка Bash в Windows 10
Начиная с Windows 10 Anniversary Edition, в Windows можно устанавливать Bash как «родную» оболочку, используя следующую команду Windows PowerShell:
Get-WindowsOptionalFeature -Online -FeatureName *linux* | Enable-WindowsOptionalFeature -NoRestart -all –online
Но заметьте, что этот функционал пока находится в стадии бета-версии и поэтому включается только в режиме разработчика (используйте Get-Help WindowsDeveloper, чтобы узнать, как исследовать режим разработчика).
К сожалению, этот функционал требует перезагрузки, но я включаю параметр –NoRestart, чтобы включение этого функционала не вызывало немедленной перезагрузки.
Репозитарии PowerShell и PowerShell Gallery
Хотя это здорово, что можно писать свои скрипты и библиотеки, скорее всего кто-то из сообщества уже сделал подобное, и вы сможете использовать это и улучшить. Однако до появления PowerShell Gallery (PowerShellGallery.com) приходилось прочесывать Интернет в поисках скриптов и модулей, которые могли быть полезны, — будь то наработки от сообщества или официальные релизы для PowerShell вроде Pscx или модуля Posh-Git. Одно из недавних расширений PowerShell (часть PowerShell 5.0), от которого я стал полностью зависимым, — поддержка нового репозитария специально для PowerShell Gallery. Вообразите, например, что вы писали какое-то время скрипт PowerShell и в процессе этого осознали, что вы должны обходить множество подводных камней, — о, если б только был какой-то способ анализа вашего кода и поиска в нем проблемных мест. Так вот теперь вы можете перейти в PowerShell Gallery и поискать в ней модуль analyze для установки. Или, что еще лучше (поскольку у вас наверняка уже открыто окно PowerShell), использовать команду Find-Module модуля PowerShellGet (включенного в PowerShell 5.0):
Find-Module *Analyze* | Select-Object Name,Description
Вывод этой команды приведен на рис. 2.
Рис. 2. Вывод команды Find-Module
Заметьте: если у вас не установлена достаточно современная версия NuGet, использование модуля PowerShellGet вызовет обновление NuGet.
Предполагая, что вы нашли нужный модуль, его содержимое можно просмотреть командой Save-Module. Для установки модуля используйте команду Install-Module (в данном случае — Install-Module PSScriptAnalyzer). Это приведет к скачиванию и установке модуля за вас, сделав доступными все функции, включенные в модуль. После установки модуля PSScriptAnalyzer можно вызвать Invoke-ScriptAnalyzer $profile для сканирования вашего профиля и выявления мест, которые анализатор считает неоптимальными. (Заметьте, что больше не надо импортировать модуль для доступа к нему. Функции модуля автоматически индексируются так, чтобы при вызове функции модуля этот модуль автоматически импортировался и был доступен по требованию.)
PowerShell Gallery конфигурируется как репозитарий по умолчанию:
>Get-PSRepository
Name InstallationPolicy SourceLocation
---- ------------------ --------------
PSGallery Untrusted https://www.powershellgallery.
com/api/v2/
В итоге Find-Module работает без проблем. Однако Install-Module будет выводить вам предупреждение о не доверяемом репозитарии. Чтобы избежать этого в предположении, что вы действительно доверяете этому репозитарию, следует задать его как доверяемое командой:
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
Apt-Get для Windows с управлением пакетами PowerShell
Те, кто поработал какое-то время IT-специалистом в мире Linux, несомненно, примут apt-get как должное — скорее всего со скриптами установки, которые загружают среду в момент запуска нового экземпляра Linux. Ну а для тех, у кого такого опыта нет, apt-get является вариантом скачивания и установки программ/пакетов и любых зависимостей прямо из Интернета через командную строку. На рис. 1 показан тривиальный пример такой установки, когда с помощью apt-get устанавливается libunwind8 libicu52, от которой зависит PowerShell (в Ubuntu 14.04). В случае PowerShell 5.0 та же функциональность имеется в Windows (даже не уверен: кричать «Ух ты!» или раздраженно вздохнуть «Наконец-то!» — возможно, и то, и другое).
Для меня самые важные усовершенствования лежат в области кросс-платформенной поддержки. Да, представьте, PowerShell теперь работает в Linux.
PowerShell 5.0 поддерживает не только репозитарии вроде PowerShell Gallery для модулей PowerShell, но и управляющие программы в Windows, называемыми пакетами (packages). Один из таких диспетчеров пакетов — Chocolatey (chocolatey.org), и вы можете добавить его как репозитарий пакетов следующей командой:
Get-PackageProvider -Name chocolatey
Это позволяет использовать PowerShell для поиска пакетов, которые были развернуты в Chocolatey. Например, если вы хотите установить Visual Studio Code, вам нужно лишь ввести такие команды:
Find-Package V*S*Code | Install-Package
Как видите, поддерживаются символы подстановки.
Другие команды Package, с которыми следует ознакомиться, доступны с помощью команды, приведенной ниже. Результаты ее выполнения показаны на рис. 3.
Get-Help "-package" | Select-Object Name,Synopsis
Рис. 3. Доступные команды Package в Windows PowerShell
Как видите, можно как получить, так и удалить пакет. Get-Package перечисляет все программы (и другие элементы), доступные из Programs and Features в Control Panel. Поэтому, если вы хотите удалить, например, Notepad2, вы могли бы использовать команду:
Get-Package Notepad2* | Uninstall-Package
Это колоссальным образом упрощает автоматизацию настройки компьютера с Windows. Я являюсь приверженцем Chocolatey вот уже несколько лет, и сейчас появилась возможность интегрировать поддержку Chocolatey непосредственно в Windows. Тем самым в конечном счете в Windows появится примерно такое же управление пакетами, как и достигаемое с помощью Apt-Get в Linux.
Репозитарий Chocolatey доступен через команды *–package* в PowerShell, но Chocolatey также можно установить напрямую. Хотя это не обязательно, установка Chocolatey напрямую иногда дает более надежный набор функционала для управления пакетами. К счастью, установка Chocolatey заключается в простом вызове команды Install-Package Chocolatey. Однако (и это пример расхождения в поведении Chocolatey, установленного напрямую и через *–Package) каталог установки по умолчанию будет зависеть от того, какой механизм установки используется. Подробнее о наборе инструментов Chocolatey, включая инструкции по установке в вашей среде, см. на chocolatey.org/install.
Работа с OData с помощью Export-ODataEndpointProxy
Другая функция PowerShell 5.0, о которой стоит упомянуть, — возможность генерации набора методов, которые обращаются к источнику данных OData, например к Visual Studio Team Services (VSTS). На рис. 4 демонстрируется выполнение Export-ODataEndpointProxy применительно к OData-сервису, в данном случае — к общедоступному примеру OData-сервиса Northwind.
Рис. 4. Генерация и вызов OData-прокси
Если вы просмотрите команды сгенерированного модуля, то заметите, что для каждой сущности (Advertisement, Category, Person и т. д.) наряду с соответствующими действиями (Get, New, Remove, Set) генерируются отдельные команды.
Обратите внимание на командную строку на рис. 4: в ней используется параметр –AllowUnsecureConnection. Это необходимо, так как OData-сервис, используемый в этом примере, не требует аутентификации или шифрования.
Преобразование из текста в объекты с помощью ConvertFrom-String
Еще одна новая команда в PowerShell 5.0 — ConvertFrom-String. Она принимает на входе структурированный текст и интерполирует структуру так, чтобы вывести объект на основе разобранного текста. Вы могли бы использовать ее. например, для разбора плоского файла или (где я нахожу ее крайне полезной) для преобразования текстового вывода от исполняемого файла в какой-либо объект.
Рассмотрим, к примеру, программу handle.exe от SysInternal, (ее можно установить командой Install-Package Handle, используя управление пакетами, как обсуждалось в предыдущем разделе). Как и следовало ожидать от утилиты командной строки, они записывает текст в stdout — в данном случае это список открытых описателей (handles), связанных с указанным именем. Но в PowerShell вы привыкли работать с объектами. И чтобы преобразовать текстовый вывод в объект, используйте функцию ConvertFrom-String, как показано на рис. 5.
Рис. 5. Использование ConvertFrom-String для разбора stdout в объект
На рис. 5 сначала отображается исходный вывод от утилиты handle.exe. Затем демонстрируется работа ConvertFrom-String без параметров. В итоге утилита ConvertFrom-String просто разбивает текст в каждой строке по пробелам.
В третьем примере демонстрируется вариант с регулярным выражением с целью тонкой настройки разбора. Но заметьте, что знакомства с регулярными выражения не требуется. Вместо этого вы можете указать шаблон (возможно, точнее будет сказать — образец) либо файла, либо строки, в которые вы вручную разбираете первые несколько элементов. Затем ConvertFrom-String использует образец разбора содержимого и интерпретирует, как разобрать остальной ввод.
В последнем примере я добавил параметр –PropertyNames, чтобы назначать осмысленные имена для вывода.
В общем, ConvertFrom-String перебрасывает мостик между мирами традиционного вывода текста в stdout и PowerShell, опирающейся на объекты. В данном случае я могу конвейеризовать вывод в Stop-Process –Id, преобразующий значение pid в значение параметра –Id.
Классы и перечисления
И наконец, я дам краткий обзор по поддержке классов и перечислений. В PowerShell 5.0 добавили два новых ключевых слова, соответствующих этим двум структурам, чтобы теперь вы могли объявить класс или перечисление прямо в PowerShell (вместо использования Add-Type и передачи C#-кода или создания экземпляра PSCustomObject). Синтаксис вполне отвечает вашим ожиданиям, как показано на рис. 6.
Рис. 6. Объявление классов и перечислений в Windows PowerShell
enum CustomProcessType {
File
Section
}
class CustomProcess {
[string]$ProcessName;
hidden [string]$PIDLabel;
[int]$PID;
hidden [string]$TypeLabel;
[CustomProcessType]$Type;
[int]$Handle;
[string]$Path;
CustomProcess(
[string]$processName,[string]$pidLabel,[int]$pid,
[string]$typeLabel,[string]$type,[int]$handle,
[string]$path) {
$this.ProcessName = $processName;
$this.PIDLabel=$pidLabel;
$this.PID=$pid;
$this.TypeLabel=$typeLabel;
$this.Type=$type;
$this.Handle=$handle;
$this.Path=$path;
}
CustomProcess() {}
GetProcess() {
Get-Process -Id $this.PID
}
static StopProcess([CustomProcess]$process) {
Stop-Process -Id $process.PID
}
}
Обратите внимание, что поддерживаются как свойства, так и методы. Есть и модификаторы объявлений вроде static и hidden. Более того, поддерживается наследование с синтаксисом, очень похожим на таковой в C#:
class Employee : Person {}
Наконец, что тоже демонстрируется на рис. 6, можно объявлять конструкторы. В этом примере я объявляю конструктор по умолчанию (без параметров) и второй конструктор, который принимает все параметры. Конструкторы вызываются через команду New-Object либо с указанием параметра –ArgumentList (где перечисляется массив аргументов конструктора), либо с передачей аргумента HashTable через параметр –Property.
ConvertFrom-String перебрасывает мостик между мирами традиционного вывода текста в stdout и PowerShell, опирающейся на объекты.
Заключение
Мы обсудили далеко не полный список новых возможностей PowerShell 5.0. Другие существенные возможности включают следующее.
- Интеграция архива (поддержка файлов .zip) командами Compress-Archive и Expand-Archive.
- Команды Get-Clipboard и Set-Clipboard, также работающие с оператором конвейера.
- Out-File, Add-Content и Set-Content включают параметр –NoNewline, обеспечивая поддержку содержимого файлов, где нет символов новой строки.
- Команда New-TemporaryFile работает аналогично [System.IO.Path]::GetTempFileName (но не идентично). Как и его .NET-эквивалент, New-TemporaryFile не удаляет временный файл, поэтому позаботьтесь о сохранении вывода, чтобы можно было удалить временный файл по окончании работы с ним.
- SymbolicLinks теперь можно управлять непосредственно из командлетов PowerShell New-Item и Remove-Item.
- PowerShell Integrated Scripting Environment (ISE) теперь поддерживает протоколирование через функции Start/Stop/Search-Transcript, которые ранее давали ошибки при вызове из PowerShell ISE.
Более того, хотя в данный момент в релизе PowerShell с открытым исходным кодом нет поддержки Open SSH, Microsoft намерена ввести эту поддержку, чтобы сделать его одним из вариантов транспорта для удаленного взаимодействия (remoting transport) в PowerShell, а также в Windows Remote Management. Появление этой поддержки ожидается буквально после публикации этой статьи.
Итак, PowerShell по-прежнему становится все лучше и лучше. Если вы еще не освоили ее, не откладывайте это в долгий ящик.
Марк Михейлис (Mark Michaelis) — учредитель IntelliTect, где является главным техническим архитектором и тренером. Почти два десятилетия был Microsoft MVP и региональным директором Microsoft с 2007 года. Работал в нескольких группах рецензирования проектов программного обеспечения Microsoft, в том числе C#, Microsoft Azure, SharePoint и Visual Studio ALM. Выступает на конференциях разработчиков, автор множества книг, последняя из которых — «Essential C# 6.0 (5th Edition)». С ним можно связаться в Twitter (@markmichaelis) или по электронной почте mark@IntelliTect.com.
Выражаю благодарность за рецензирование статьи экспертам IntelliTect Кевину Босту (Kevin Bost), Филу Споукасу (Phil Spokas) и Майклу Стоуксбери (Michael Stokesbary).