powershell - 无论脚本是在 “regular” Powershell控制台还是在Powershell ISE中运行,如何以相同的方式处理错误?

标签 powershell error-handling

我有这个简单的脚本:

$ErrorActionPreference = "Stop"
try 
{ 
    cmd /c mklink a .\DataSvc.sln 
} 
catch 
{ 
    "Failed" 
}

(文件DataSvc.sln存在)

当我在ISE powershell控制台中运行它时,它会显示“失败”,而当我从“常规” powershell控制台中进行操作时,它会显示“您没有足够的特权来执行此操作”。

ISE:

enter image description here

常规:

enter image description here

在两种情况下,我应该如何编写它以便打印“失败”?

编辑1

您必须在Windows 10开发人员模式关闭的情况下以普通帐户(不是提升帐户)身份运行它。如果您不知道什么是Windows 10开发人员模式,则可以(针对此问题)。

最佳答案

不幸的是,不同的主机对外部程序的stderr输出进行不同的处理。

  • ISE将stderr输出路由到PowerShell自己的错误流,这解释了为什么写入stderr的任何内容都会触发try/catch处理程序。
  • 在侧节点上:考虑使用Visual Studio Code从过时的ISE切换到PowerShell extension。将来的开发工作集中在此,并且行为与控制台没有什么不同(至少在这方面)。
  • 常规控制台将stderr输出修补到控制台,在这种情况下,不会触发任何错误。

  • 由于存在bug,您当前(Windows PowerShell v5.1/PowerShell Core v6.1)可以通过在PowerShell中重定向流号2来在控制台中触发错误:
    $ErrorActionPreference = "Stop"
    try {
      cmd /c 'echo tostderr >&2' 2>&1 # even 2>$null would trigger an error(!)
    } catch {
      "Failed"
    }
    

    但是,我不会依赖它,因为该错误可能会(而且希望会)得到修复。

    退后一步:正如注释中的链接所暗示的那样,外部程序是否失败应该仅从其退出代码中得出,而不应从存在stderr输出中得出,因为许多程序使用stderr输出来报告错误以外的信息(例如作为诊断信息或仅作为警告)。

    因此,应单独使用if ($LASTEXITCODE -ne 0)来确定失败。

    如果由于某种原因您确实需要根据stderr输出的存在来推断出失败-例如,由于某些程序无法正确地反射(reflect)其退出代码中的失败-您可以尝试以下方法,该方法现在和之后都适用前述错误已修复:
    $ErrorActionPreference = "Stop"
    try {
      cmd /c 'echo tostderr >&2' 2>&1 | ForEach-Object {
        if ($_ -is [System.Management.Automation.ErrorRecord]) { Throw $_ }
        $_
      }
    } catch {
      "Failed"
    }
    

    这依赖于将错误流合并到成功流中,然后根据其类型来检测源自stderr的行。

    请注意,虽然在PowerShell内部,您可以使用公用参数-ErrorVariable/-ev将变量的命令输出错误收集起来,但是在调用外部程序时没有类似的机制。但是,在this GitHub issue中提出了引入这种机制的建议。

    关于powershell - 无论脚本是在 “regular” Powershell控制台还是在Powershell ISE中运行,如何以相同的方式处理错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51431975/

    相关文章:

    error-handling - 如何全局禁用 Pylint 特定的错误消息?

    c# - 如何处理 Global.asax Application_Start 中的错误?

    sharepoint - 获取网络分析

    powershell - 检查 Powershell 中的范围

    powershell - Powershell:AD-GET无法与变量一起使用

    arrays - 这个 select 语句中的 N 和 E 代表什么

    variables - 如何使用PowerShell变量作为命令参数?

    jquery - rails 4- 401未经授权的错误处理

    error-handling - 引发一些进行中的运行时错误4GL

    Excel VBA 错误从控制表单框中调用 Sub