Используйте Begin, Process, End in Scriptblock

Можно ли использовать расширенные функции Begin, Process, End в скрипте-блоке?

Например, у меня есть следующий блок скриптов:

$startStopService = {
Param(
    [bool] $startService)    

  if ($startService){
     ...
     Start-Service "My-Service"
  }
  else {
     Stop-Service "My-Service"
  }
}

Так как я хочу иметь возможность контролировать подробный вывод блока скриптов, я хочу изменить блок на:

$startStopService = {
Param(
    [bool] $startService)    

  Begin {
     $oldPreference = $VerbosePreference 
     $VerbosePreference = $Using:VerbosePreference
  }
  Process {
     if ($startService){
        ...
        Start-Service "My-Service"
     }
     else {
        Stop-Service "My-Service"
     }
  }
  End {
     # Restore the old preference
     $VerbosePreference = $oldPreference 
  }
}

Можно ли использовать Begin, Process, End здесь, хотя скрипт-блок не является командлетом? Я просто хочу, чтобы VerbosePreference восстанавливается старое значение независимо от того, произошла ошибка или нет. Конечно, я мог бы использовать try{}finally{} в качестве альтернативы, но я считаю, что Begin, Process, End более интуитивно понятен

Спасибо

1 ответ

Решение

Это возможно, как описано в about_script_blocks:

Как и функции, блоки скриптов могут включать в себя ключевые слова DynamicParam, Begin, Process и End. Для получения дополнительной информации см. About_Functions и about_Functions_Advanced.


Чтобы проверить это, я изменил ваш скрипт и запустил это:

$startStopService = {
Param(
    # a bool needs $true or $false passed AFAIK
    # A switch is $true if specified, $false if not included
    [switch] $startService 
 )    

  Begin {
     $oldPreference  = $VerbosePreference 
     Write-Output "Setting VerbosePreference to Continue"

     # $Using:VerbosePreference gave me an error
     $VerbosePreference = "Continue"
  }
  Process {
     if ($startService){
        Write-Verbose "Service was started"
     }
     else {
        Write-Verbose "Service was not started"
     }
  }
  End {
     # Restore the old preference
     Write-Output "Setting VerbosePreference back to $oldPreference"
     $VerbosePreference = $oldPreference 
  }

}

Write-Verbose "This message will not print if VerbosePreference is the default SilentlyContinue"

. $startStopService -startService

Write-Verbose "This message will not print if VerbosePreference is the default SilentlyContinue"

Какой функционал вам нужен? Если вы хотите печатать подробные сообщения при запуске скриптового блока, но не меняете $VerbosePreference в остальной части сценария рассмотрите возможность использования [CmdletBinding()] и -Verbose флаг:

$startStopService = {
    [CmdLetBinding()]
    Param(
        [switch] $startService
    )

     Write-Verbose "This is a verbose message"

}
Write-Verbose "This message will not print if VerbosePreference is the default SilentlyContinue"

. $startStopService -verbose

Write-Verbose "This message will not print if VerbosePreference is the default SilentlyContinue"

Редактировать - Invoke-Command

После вашего комментария я изучаю функциональность Invoke-Command, И нашел много вещей, которые не работают.

Короткая версия, которую я считаю наиболее полезной для вас: вы можете объявить $VerbosePreference = "Continue" в пределах блока сценария, и это будет ограничено областью блока сценария. Нет необходимости менять обратно после.

$startStopService = {
    [CmdLetBinding()]
    Param(
        [parameter(Position=0)]
        [switch]$startStopService,

        [parameter(Position=1)]
        [switch]$Verbose
    )

    if($Verbose){
        $VerbosePreference = "Continue"
    }

    Write-Verbose "This is a verbose message"

}

Write-output "VerbosePreference: $VerbosePreference"
Write-Verbose "This message will not print if VerbosePreference is the default SilentlyContinue"

Invoke-Command -Scriptblock $startStopService -ArgumentList ($true,$true)

Write-output "VerbosePreference: $VerbosePreference"
Write-Verbose "This message will not print if VerbosePreference is the default SilentlyContinue"

Пытаясь передать -Verbose переключить CommonParameter на Invoke-Command был не ходи. Это использует стандарт Verbose параметр переключателя, который позволяет передавать $true / $false (или опустить), чтобы контролировать подробный вывод.

Связанные с:
about_Functions
about_Functions_Advanced

Другие вопросы по тегам