【问题标题】:Cross edition exception handling with Powershell web cmdlets使用 Powershell Web cmdlet 处理跨版本异常
【发布时间】:2018-10-30 10:59:22
【问题描述】:

我有一个针对 Windows PowerShell 5.1 运行的现有 PowerShell 模块。它在很大程度上取决于 Invoke-WebRequestInvoke-RestMethod cmdlet,它们在 5.1 和 PowerShell Core 6 之间有一些 fairly significant changes

我已经设法使大部分代码在不同版本(桌面/核心)之间工作,但我遇到的最后一件事是处理 HTTP 失败响应引发的异常。现有代码看起来或多或少是这样的。

try {
    $response = Invoke-WebRequest @myparams -EA Stop
    # do more stuff with the response
} catch [System.Net.WebException] {
    # parse the JSON response body for error details
}

除了来自服务器的 HTTP 响应代码失败所生成的异常之外,我不一定要捕获任何异常。 Core 版返回的异常类型与桌面版不同,需要单独的代码路径来解析响应。所以最初我尝试了这个:

try {
    $response = Invoke-WebRequest @myparams -EA Stop
    # do more stuff with the response
} catch [System.Net.WebException] {
    # Desktop: parse the JSON response body for error details
} catch [Microsoft.PowerShell.Commands.HttpResponseException] {
    # Core: parse the JSON response body for error details
}

在 Core 中运行时可以正常工作。但在 Desktop 中运行时,我收到 Unable to find type [Microsoft.PowerShell.Commands.HttpResponseException] 错误。

解决此问题的最佳方法是什么?我是否需要捕获所有异常,类型上的字符串匹配,然后重新抛出我不想要的?有没有一种更优雅的方式,不涉及为 PowerShell 的桌面版和核心版发布单独的模块版本?

【问题讨论】:

  • 我确实会采用文本方式。 catch [Exception],然后打开$_.Exception.GetType().FullName 并使用默认的throw 操作。这应该可以很好地跨平台工作,并且没有比您的示例更多的代码行。

标签: powershell powershell-core


【解决方案1】:

我可能会建议您围绕执行异常处理的 cmdlet 进行精简包装,并且您可能会创建自己的一致异常类,并且每个版本都会抛出相同的异常类。

在运行时,您确定您的版本/版本,并设置一个您想要使用的别名。

例子:

function Invoke-PS51WebRequest {
[CmdletBinding()]
param(...)

    try {
        Invoke-WebRequest @PSBoundParameters -EA Stop
        # return the response
    } catch [System.Net.WebException] {
        # create a new exception
        throw [My.Custom.Exception]$_
    }
}

function Invoke-PS6XWebRequest {
[CmdletBinding()]
param(...)

    try {
        Invoke-WebRequest @PSBoundParameters -EA Stop
        # return the response
    } catch [System.Net.WebException] {
        # Desktop
        throw [My.Custom.Exception]$_
    } catch [Microsoft.PowerShell.Commands.HttpResponseException] {
        # Core
        throw [My.Custom.Exception]$_
    }
}

switch ($PSVersionTable)
{
    { $_.Is51 } { Set-Alias -Name Invoke-WebRequest -Value Invoke-PS51WebRequest -Force }
    { $_.Is6X } { Set-Alias -Name Invoke-WebRequest -Value Invoke-PS6XWebRequest -Force }
}

try {
    Invoke-WebRequest @myParams -ErrorAction Stop
} catch [My.Custom.Exception] {
    # do something
}

这需要大量工作(正确解析异常,可能会产生超过 2 个这样的变体,确定您在哪个平台上是真实的,因为 $PSversionTable.Is51.Is6X 不是真实的,创建您自己的异常类,创建它的适当实例,而不是将 $_ 转换为它,等等)。

我还演示了覆盖实际名称 Invoke-WebRequest,但我建议使用您自己的名称 Invoke-MyCustomWebRequest 并在整个代码中使用它。这将使事情更易于管理。

【讨论】:

  • 现在执行错误处理的函数已经是 Invoke-WebRequest 的包装器,它返回从响应正文解析的自定义异常类型。因此,实现这一目标可能不需要太多工作。谢谢你的主意。我很好奇人们可能会想出什么其他答案。但如果没有添加任何实质性内容,我会将其标记为已接受。
猜你喜欢
  • 2019-04-12
  • 2014-02-28
  • 1970-01-01
  • 2013-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-20
相关资源
最近更新 更多