Резюме: Microsoft Windows PowerShell MVP Richard Siddaway рассказывает об ограничениях в рабочих процессах Windows PowerShell.
Microsoft Scripting Guy, Ed Wilson на связи. Сегодня мы публикуем второй пост из серии статей об использовании рабочих процессов за авторством Windows PowerShell MVP Richard Siddaway.
Заметка: Первый пост «PowerShell Workflows: Основы» рассказывает об основных концепциях рабочих процессов. Перед чтением этой статьи вам стоит ознакомиться с ним.
Richard Siddaway написал несколько гостевых постов, кроме этого он является автором двух книг по Windows PowerShell. Последняя его книга, PowerShell in Depth написана в соавторстве двумя другими MVP – Don Jones и Jeffrey Hicks.
Итак.
В прошлом посте я рассказал об основах рабочих процессов Windows PowerShell. Я также коснулся нескольких ограничений рабочих процессов. Думаю, пришла пора рассмотреть их поближе и определить обходные пути для их преодоления.
Ограничения рабочих процессов можно разделить на следующие группы:
- Области действия переменных
- Десериализованные объекты
- Командлеты, для которых не было создано активностей
- Неподдерживаемые активности Windows PowerShell
Неподдерживаемые активности Windows PowerShell
Некоторые ключевые слова и используемые техники Windows PowerShell не поддерживаются в рабочих процессах. Они приведены в следующей таблице.
Неподдерживаемые техники Windows PowerShell | ||
Begin,Process,End | Break,Continue | Подвыражения |
Множественное назначение переменных | Изменение переменных цикла | Динамические параметры |
Задание свойств | Оператор точка | Расширенная валидация параметров |
Позиционные параметры | Выражение Switch | Выражение Trap |
Встроенная справка | Задание дисковых переменных | Вызов методов из объектов |
Единственнное #requires |
Еще одно ограничение которое мне встречалось, это использование пользовательских дисков Windows PowerShell – если они присутствуют, рабочие процессы могут перестать выполняться.
Некоторые их этих ограничений, например использование выражения trap, не такая уж большая проблема. Вместо него вы можете использовать try-catch. Другие ограничения приносят больше неудобств, например невозможность использовать выражение switch. Если вы попробуете использовать switch в рабочем процессе:
workflow testswitch {
param (
[string]$os
)
switch ($os) {
«XP» {«Time to upgrade»}
«Windows7» {«OK — but not the lastest»}
«Windows 8» {«Latest and greatest»}
}
}
то вы получите море красных сообщений:
At line:5 char:2
+ switch ($os) {
+ ~~~~~~~~~~~~~~
Case-insensitive switch statements are not supported in a Windows PowerShell workflow. Supply the -CaseSensitive flag, and ensure that case clauses are written appropriately. To write a case-insensitive case statement, first convert the input to either uppercase or lowercase, and update the case clauses to match.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : SwitchCaseSensitive
Прочитав сообщение об ошибке вы можете подумать, что можно сделать следующее:
workflow testswitchi {
param (
[string]$os
)
switch -CaseSensitive ($os.ToUpper()) {
«XP» {«Time to upgrade»}
«WINDOWS7» {«OK — but not the lastest»}
«WINDOWS 8» {«Latest and greatest»}
}
}
Нет, опять ошибка.
At line:5 char:25
+ switch -CaseSensitive ($os.ToUpper()) {
+ ~~~~~~~~~~~~~
Method invocation is not supported in a Windows PowerShell Workflow. To use .NET Framework scripting, place your commands in an inline script:
InlineScript {
}.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MethodInvocationNotSupported
Ну что ж, воспользуемся InlineScript.
workflow testswitch {
param (
[string]$os
)
InlineScript {
switch ($using:os) {
«XP» {«Time to upgrade»}
«Windows7» {«OK — but not the lastest»}
«Windows 8» {«Latest and greatest»}
}
}
}
В этом случае все работает так, как от него ожидается.
Еще одно ограничение, невозможность использования блоков BEGIN, PROCESS и END, которые вы можете использовать в функциях, затрагивает вещи, которые просто не укладываются в концепцию рабочих процессов. Другое ограничение, оказывающее значительное влияние – это невозможность использования справки на основе комментариев. Вы должны использовать XML-файлы. Существует несколько способов генерации этих файлов, один из наиболее простых – это использовать InfoPath, как описывает James O’Neill.
Невозможность валидации параметров может стать значительным неудобством, если ваши рабочие процессы используют большое их число. Для этого ограничения не существует обходных путей кроме написания кода валидации в самом рабочем процессе.
Вы уже видели выражение $using:computer в предыдущем посте и $using:os в скрипте, касающемся использования выражения switch. Этот синтаксис используется для преодоления ограничений, относящихся ко второй группе – области действия переменных.
Области действия переменных
В рабочих процессах существуют следующие ограничения на использование переменных:
- Переменные, определенные в верхней области видны в нижних областях, но не видны в блоках InlineScript
- Невозможно определить переменную в нижней области с именем, совпадающим с переменной в верхней области
- Если определить или переопределить переменную, вы можете вы можете без всяких проблем использовать ее в этой области
- Не существует области $global
- Для использования в блоке InlineScript переменных, определенных в верхней области, нужно указывать «$using»
- Изменение в блоке InlineScript переменной, определенной в верхней области требует использования временной переменной
- Для изменения переменных, определенных в верхней области нужно использовать «$workflow»
- Нельзя использовать подвыражения
Это может показаться несколько запутанным, но демонстрация должна внести некоторую ясность. Я рекомендую вам запустить этот код и рассмотреть полученные результаты.
workflow demo-scope {
# This is a workflow top-level variable
$a = 22
«Initial value of A is: $a»
# Access $a from Inlinescript (bringing a workflow variable to the Windows PowerShell session) using $using
inlinescript {«PowerShell variable A is: $a»}
inlinescript {«Workflow variable A is: $using:a»}
## changing a variable value
$a = InlineScript {$b = $Using:a+5; $b}
«Workflow variable A after InlineScript change is: $a»
parallel {
sequence {
# Reading a top-level variable (no $workflow: needed)
«Value of A inside parallel is: $a»
# Updating a top-level variable with $workflow:
$workflow:a = 3
}
}
«Updated value of A is: $a»
}
demo-scope
После запуска рабочего процесса вы должны увидеть нечто подобное.
Initial value of A is: 22
PowerShell variable A is:
Workflow variable A is: 22
Workflow variable A after InlineScript change is: 27
Value of A inside parallel is: 27
Updated value of A is: 3
Рабочий процесс начинается с определения переменной, $a=22, затем он выводит ее значение. Если вы попытаетесь получить содержимое переменной, определенной в верхней области, из блока InlineScript, ничего не получится, как показано во второй строке вывода. Для доступа к переменной вам нужно использовать $using. Если вам нужно изменить значение этой переменной, то для этого потребуется использовать вторую переменную и затем возвратить новое значение.
$a = InlineScript {$b = $Using:a+5; $b}
Вывод показывает, что теперь переменная обладает значением 27.
Доступ к переменной из блока parallel происходит без каких-либо сложностей. Если вам нужно изменить значение этой переменной в блоке parallel, потребуется указать $workflow.
Подводя итоги работы с переменными: не переусложняйте скрипт и будьте осторожны.
Десериализация объектов
Третье ограничение заключается в том, что объекты в рабочих процессах десериализованы. Это сродни с удаленным выполнением команд в Windows PowerShell (что неудивительно, так как рабочие процессы используют тот же транспортный механизм). Можно заметить что десериализация объектов встречается все чаще и чаще. Области, где она встречается:
- Удаленная работа в Windows PowerShell
- Удаленный доступ посредством CIM-сессий
- Командлеты WSMAN
- Рабочие процессы
Возможно это становится стандартным подходом к работе в Windows PowerShell.
Десериализованный объект обладает свойствами объекта, но не его методами. Другими словами, он инертный. Огромная часть кода Windows PowerShell делает нечто подобное:
$string = «abcde»
$string.ToUpper()
$os = Get-WmiObject -Class Win32_OperatingSystem
$os.ConvertToDateTime($os.LastBootUpTime)
Однако в случае с рабочими процессами это не сработает.
workflow test2 {
$string = «abcde»
$string.ToUpper()
$os = Get-WmiObject -Class Win32_OperatingSystem
$os.ConvertToDateTime($os.LastBootUpTime)
}
При попытке запуска появится сообщение об ошибке, указывающее, что вызов методов не поддерживается. Однако, вы можете сделать следующее:
workflow test2 {
inlinescript {
$string = «abcde»
$string.ToUpper()
$os = Get-WmiObject -Class Win32_OperatingSystem
$os.ConvertToDateTime($os.LastBootUpTime)
}
}
Не пытайтесь использовать переменные, содержащие объекты из верхней области действия, для вызова методов – это не сработает.
Подводя итоги, касательно десериализованных объектов – если вам нужно вызвать метод объекта, делайте это из блока InlineScript. Помните, что вы можете вкладывать блоки InlineScript в блоки Parallel.
Командлеты, для которых не было создано активностей
Последнее ограничение касается командлетов, которые не для которых не было создано соответствующих активностей. Как вы помните, в предыдущем посте нам встретилась проблема использования командлетов Format* в рабочих процессах. Это можно обойти, используя InlineScript.
workflow foreachpitest {
param([string[]]$computers)
foreach –parallel ($computer in $computers){
InlineScript {
Get-WmiObject –Class Win32_OperatingSystem –ComputerName $using:computer |
Format-List
}
}
}
Другие командлеты, которые не могут быть использованы в рабочих процессах приведены в таблице. Вы можете использовать их внутри InlineScript.
Неподдерживаемые командлеты (группы) | Причина |
*Alias, *FormatData, *History, *Location, *PSDrive, *Transcript, *TypeDate, *Variable, Connect/Disconnect-Wsman | Вносят изменения только в текущую сессию, поэтому не требуются в рабочих процессах |
Show-Command, Show-ControlPanelItem, Get-Credential, Show-EventLog, Out-Gridview, Read-Host, Debug-Process | Рабочие процессы не поддерживают интерактивные командлеты |
*BreakPoint, Get-PSCallStack, Set-PSDebug | Рабочие процессы не поддерживают отладку скриптов |
*Transaction | Рабочие процессы не поддерживают транзакции |
Format* | Отсутствует поддержка форматирования |
*PSsession, *PSsessionoption | Удаленный доступ контролируется рабочим процессом |
Export-Console,Get-ControlPanelItem, Out-Default, Out-Null, Write-Host, Export-ModuleMember, Add-PSSnapin, Get-PSSnapin, Remove-PSSnapin, Trace-Command |
Ниже приведена таблица с командлетами, которые поддерживают только локальное выполнение, при использовании их в рабочем процессе.
Add-Member | Compare-Object | ConvertFrom-Csv | ConvertFrom-Json |
ConvertFrom-StringData | Convert-Path | ConvertTo-Csv | ConvertTo-Html |
ConvertTo-Json | ConvertTo-Xml | ForEach-Object | Get-Host |
Get-Member | Get-Random | Get-Unique | Group-Object |
Measure-Command | Measure-Object | New-PSSessionOption | New-PSTransportOption |
New-TimeSpan | Out-Default | Out-Host | Out-Null |
Out-String | Select-Object | Sort-Object | Update-List |
Where-Object | Write-Debug | Write-Error | Write-Host |
Write-Output | Write-Progress | Write-Verbose |
Если вам нужно запустить их удаленно, как вы наверное уже догадались, используйте InlineScript.
Узнать больше об ограничениях рабочих процессов вы можете в файлах справки:
about_ActivityCommonParameters
about_Checkpoint-Workflow
about_Foreach-Parallel
about_InlineScript
about_Parallel
about_Sequence
about_Suspend-Workflow
about_WorkflowCommonParameters
about_Workflows
Если вы только запустили PowerShell, вы можете их не увидеть. Импортируйте модуль PSWorkflow и они станут доступными.
В этой статье я попытался рассказать об ограничениях, с которыми вы можете встретиться, используя рабочие процессы. Как я сказал в предыдущей статье, «PowerShell Workflows: Основы», если вы не знаете об ограничениях, вы можете здорово о них споткнуться.
В следующей статье мы рассмотрим вложенные рабочие процессы а также использование функций Windows PowerShell с рабочими процессами.
~Richard.
Автор:
Ed Wilson, Microsoft Scripting Guy
Оригинал:
http://blogs.technet.com/b/heyscriptingguy/archive/2013/01/02/powershell-workflows-restrictions.aspx
Страницы в социальных сетях:
Twitter: https://twitter.com/vsseth
Facebook: https://fb.com/inpowershell
VKontakte: https://vk.com/inpowershell