【问题标题】:PowerShell try/catch/finallyPowerShell tr​​y/catch/finally
【发布时间】:2011-10-10 09:17:36
【问题描述】:

我最近编写了一个运行良好的 PowerShell 脚本 - 但是,我现在想升级脚本并添加一些错误检查/处理 - 但我似乎遇到了第一个障碍。为什么下面的代码不起作用?

try {
  Remove-Item "C:\somenonexistentfolder\file.txt" -ErrorAction Stop
}

catch [System.Management.Automation.ItemNotFoundException] {
  "item not found"
}

catch {
  "any other undefined errors"
  $error[0]
}

finally {
  "Finished"
}

错误在第二个 catch 块中被捕获 - 您可以看到来自 $error[0] 的输出。显然我想在第一个街区抓住它。我错过了什么?

【问题讨论】:

    标签: powershell try-catch block


    【解决方案1】:

    这很奇怪。

    我检查了ItemNotFoundException 的基类并测试了以下多个catches 以查看捕获什么:

    try {
      remove-item C:\nonexistent\file.txt -erroraction stop
    }
    catch [System.Management.Automation.ItemNotFoundException] {
      write-host 'ItemNotFound'
    }
    catch [System.Management.Automation.SessionStateException] {
      write-host 'SessionState'
    }
    catch [System.Management.Automation.RuntimeException] {
      write-host 'RuntimeException'
    }
    catch [System.SystemException] {
      write-host 'SystemException'
    }
    catch [System.Exception] {
      write-host 'Exception'
    }
    catch {
      write-host 'well, darn'
    }
    

    事实证明,输出是'RuntimeException'。我也尝试了一个不同的例外CommandNotFoundException

    try {
      do-nonexistent-command
    }
    catch [System.Management.Automation.CommandNotFoundException] {
      write-host 'CommandNotFoundException'
    }
    catch {
      write-host 'well, darn'
    }
    

    正确输出'CommandNotFoundException'

    我隐约记得在其他地方(尽管我再也找不到)读到了与此相关的问题。在异常过滤无法正常工作的这种情况下,他们会捕获最接近的Type,然后使用switch。以下只是捕获Exception 而不是RuntimeException,但是switch 相当于我的第一个示例,它检查ItemNotFoundException 的所有基本类型:

    try {
      Remove-Item C:\nonexistent\file.txt -ErrorAction Stop
    }
    catch [System.Exception] {
      switch($_.Exception.GetType().FullName) {
        'System.Management.Automation.ItemNotFoundException' {
          write-host 'ItemNotFound'
        }
        'System.Management.Automation.SessionStateException' {
          write-host 'SessionState'
        }
        'System.Management.Automation.RuntimeException' {
          write-host 'RuntimeException'
        }
        'System.SystemException' {
          write-host 'SystemException'
        }
        'System.Exception' {
          write-host 'Exception'
        }
        default {'well, darn'}
      }
    }
    

    这应该写'ItemNotFound'

    【讨论】:

      【解决方案2】:

      -ErrorAction Stop 正在为你改变一切。尝试添加这个,看看你会得到什么:

      Catch [System.Management.Automation.ActionPreferenceStopException] {
      "caught a StopExecution Exception" 
      $error[0]
      }
      

      【讨论】:

      • 这很有趣,考虑到$_.ExceptionItemNotFoundException 而不是ActionPreferencesStopException。我打赌后者从RuntimeException开车。
      • 我认为你是对的。我喜欢你的开关版本。更符合史蒂夫试图做的事情。
      • 对,这里的麻烦是它是一个非终止错误。因此,即使它是 ItemNotFoundException,除非包裹在 ActionPreferencesStopException 中,否则它实际上不会被抛出。作为开发人员,这让我很恼火。 :)
      • @JasonMArcher 似乎是旧版本中的一个错误。这在 Powershell 5.0 中按预期对我有用 那就是它捕获了ItemNotFoundException
      • @JasonS 是的,看起来您不再需要担心异常被包装了。
      猜你喜欢
      • 1970-01-01
      • 2020-02-09
      • 1970-01-01
      • 2015-12-14
      • 1970-01-01
      • 2022-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多