【问题标题】:Use Begin, Process, End in Scriptblock在脚本块中使用开始、处理、结束
【发布时间】:2017-07-03 20:25:08
【问题描述】:

是否可以在脚本块中使用高级功能特性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,尽管脚本块不是 cmdlet?我只是希望VerbosePreference 恢复到旧值,无论是否发生错误。当然我可以使用try{}finally{} 作为替代,但我发现Begin, Process, End 更直观。

谢谢

【问题讨论】:

    标签: powershell


    【解决方案1】:

    这是可能的,如about_script_blocks中所述:

    与函数一样,脚本块可以包含 DynamicParam、Begin、 处理和结束关键字。有关详细信息,请参阅 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 的功能。并且发现很多东西都不行。

    我认为对您最有用的简短版本:您可以在脚本块中声明$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

    【讨论】:

    • 我正在寻找您答案的第二个选项 (CmdletBinding)。简短的问题:CmdletBinding 也可以在Invoke-Command 工作吗?假设Invoke-Command -session $remoteSession -scriptblock $startStopService -verbose
    • @Moerwald 简短的版本是它应该,根据[<CommonParameters>] in the documenation。但是当我尝试它时它不起作用。搜索,我找到了您已经阅读过的this post。它提到这是一个错误;不确定是这种情况还是我们的做法有误。
    • 谢谢你的答案。是的,我读过这篇文章。由于它大约 3 岁,我认为可能有更好的解决方法。
    • @Moerwald 同意。经过一些研究,我没有发现太多,但看到了解决方法的编辑答案。在您的评论中直接传递-Verbose 是不可能的AFAIK。 -ArgumentList 可以使用,但无法通过命名参数使其 100% 工作。
    猜你喜欢
    • 2015-09-11
    • 2011-01-03
    • 2022-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-13
    • 2012-10-26
    • 2019-09-08
    相关资源
    最近更新 更多