使用 Powershell web cmdlet 进行跨版本异常处理

Cross edition exception handling with Powershell web cmdlets

我有一个针对 Windows PowerShell 5.1 运行的现有 PowerShell 模块。它在很大程度上取决于 5.1 和 PowerShell Core 6 之间的 Invoke-WebRequest and Invoke-RestMethod cmdlets which have some fairly significant changes

我已经设法使大部分代码在不同版本之间工作 (Desktop/Core),但我遇到的最后一件事是处理 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 响应代码生成的异常之外,我不一定要捕获任何异常。核心版返回的异常类型与桌面版不同,需要单独的代码路径来解析响应。所以最初我试过这个:

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 中 运行 时可以正常工作。但是当在桌面中 运行 时,我得到一个 Unable to find type [Microsoft.PowerShell.Commands.HttpResponseException] 错误。

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

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

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

示例:

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 不是真实的,创建您自己的异常 class,创建它的适当实例而不是将 $_ 强制转换为它,等等)。

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