Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
什么';在powershell模块函数中发出错误的正确方法是什么?_Powershell_Powershell 5.0 - Fatal编程技术网

什么';在powershell模块函数中发出错误的正确方法是什么?

什么';在powershell模块函数中发出错误的正确方法是什么?,powershell,powershell-5.0,Powershell,Powershell 5.0,我已经读了很多关于powershell错误处理的书,现在我对在任何给定情况下应该做什么(错误处理)感到非常困惑。我正在使用powershell 5.1(而不是core)。 话虽如此: 假设我有一个模块,其函数类似于以下模拟: function Set-ComputerTestConfig { [CmdletBinding()] param( [Parameter(Position=0, Mandatory=$true)] [ValidateNotNullOrEmpty()

我已经读了很多关于powershell错误处理的书,现在我对在任何给定情况下应该做什么(错误处理)感到非常困惑。我正在使用powershell 5.1(而不是core)。 话虽如此: 假设我有一个模块,其函数类似于以下模拟:

function Set-ComputerTestConfig {
  [CmdletBinding()]
  param(
    [Parameter(Position=0, Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [string] $Name)

begin { ... }
process { 
 # task 1
 # task 2 => results in a failure that prevents further tasks
 # task 3
 # task 4
}
end { ... }
假设对于我传递给这个函数的每个计算机名,我有4个任务要完成,但是如果其中任何一个任务失败,我就不能继续执行其余的任务。
我应该如何产生一个错误(最佳实践),使其停止对该特定计算机名的“处理”,但有效地继续处理管道

使用Try…Catch-确保所有命令都使用
-ErrorAction Stop
开关或将环境设置为出错时停止,例如
$ErrorActionPreference='Stop'

function Set-ComputerTestConfig {
  [CmdletBinding()]
  param(
    [Parameter(Position=0, Mandatory=$true)]
    [ValidateNotNullOrEmpty()]


    [string] $Name)

begin { ... }
process {
    Try {
        # task 1
        # task 2 => results in a failure that prevents further tasks
        # task 3
        # task 4
    }
    Catch {
        Write-Host "One of the tasks has failed`nError Message:"
        Write-Host $_
    }
}
end { ... }
  • 如果要继续处理来自管道的输入,必须发出非终止错误

    • 写入错误
      写入非终止错误;它写入PowerShell的错误流,而不会在幕后生成异常;执行继续正常进行

      • 如果.NET方法调用是错误源(如您的情况),请将其包装在
        try
        /
        catch
        中,并在
        catch
        块中调用
        Write error-ErrorRecord$:

        • try{;..}catch{Write Error-ErrorRecord$\u}
      • 不幸的是,从PowerShell Core 7.0.0-preview.4开始,
        写入错误
        并没有完全按照预期运行,因为它没有在调用方上下文中将自动成功状态变量
        $?
        设置为
        $false
        。目前唯一的解决方法是确保您的函数/脚本是一个,并使用
        $PSCmdlet.WriteError()
        ;从
        catch
        块中,您可以简单地使用
        $PSCmdlet.WriteError($\uq)
        ,但是从头开始创建自己的错误非常麻烦-请参阅

  • 如果要立即停止处理,请使用终止错误:

    • throw
      创建终止错误。
      • 不幸的是,
        throw
        创建了一种比二进制cmdlet发出的更基本的终止错误:与(编译)cmdlet发出的终止错误语句不同,
        throw
        创建了一个脚本终止(致命)错误

        • 也就是说,默认情况下,二进制cmdlet的语句终止错误只会终止手头的语句(管道)并继续执行封闭脚本,而默认情况下,
          throw
          会中止整个脚本(及其调用者)
        • 讨论这种不对称性
      • 同样,该解决方案要求您的脚本/函数是高级脚本/函数,这使您能够调用
        $PSCmdlet.throwterminingerror()
        ,而不是
        throw
        ,从而正确生成语句终止错误;与使用
        $PSCmdlet.WriteError()
        一样,您只需从
        catch
        块中使用
        $PSCmdlet.throwterminingerror($\ux)
        ,但从头开始编写自己的语句终止错误非常麻烦

  • 至于
    $ErrorActionPreference='Stop'

    • 这会将所有错误类型转换为脚本终止错误,并且至少高级函数/脚本(那些预期像cmdlet一样工作的函数/脚本)不应设置它

    • 相反,让脚本/函数发出适当类型的错误,并让调用者通过公共
      -ErrorAction
      参数或
      $ErrorActionPreference
      变量控制对这些错误的响应

      • 注意事项:如果调用者位于模块外部或不同模块中,则模块中的函数看不到调用者的首选项变量-这一基本问题将在中讨论
  • 至于在函数脚本内部传递错误/重新打包错误

    • 非终止错误会自动传递

      • 如果需要,您可以使用
        -ErrorAction Ignore
        2>$null
        抑制它们,还可以选择使用
        -ErrorVariable
        公共参数(与
        -ErrorAction SilentlyContinue
        组合)收集它们以供以后处理
    • 脚本终止错误传递的意义是,默认情况下,整个调用堆栈与代码一起终止

    • 语句终止错误会写入错误流,但默认情况下脚本/函数会继续运行

      • 使用
        try{…}catch{throw}
        将它们转换为脚本终止错误,或者

      • 。。。使用
        $PSCmdlet.throwterminingerror($\u)
        而不是
        throw
        将错误作为终止错误的语句进行中继

进一步阅读

  • 关于何时发出终止错误与非终止错误的指南在中

  • 有关PowerShell错误处理的全面概述,请参阅


为什么不使用一个try-catch块,其中所有四个任务都在一个try块中,并且捕获将继续到下一台计算机?try-catch会捕获每个任务产生的所有内容吗(我的印象是某些错误没有被捕获)。写主机不是总是错误的吗?我要求提供建议的最佳实践,因为powershell似乎是一种非常规范的语言,遵循这些语言是值得的。这在很大程度上取决于这些任务中的代码,但通常情况下,如果任何cmdlet在Try块中失败,它会移到Catch块。你