PowerShell Workflows: Ограничения – Hey, Scripting Guy! Blog

Резюме: 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


Реклама

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход /  Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход /  Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход /  Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход /  Изменить )

w

Connecting to %s