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

Rya*_*ger 5 powershell powershell-core

我有一个针对 Windows PowerShell 5.1 运行的现有 PowerShell 模块。它在很大程度上取决于Invoke-WebRequestInvoke-RestMethodcmdlet,它们在 5.1 和 PowerShell Core 6 之间有一些相当重大的变化

我已经设法使大部分代码在版本(桌面/核心)之间工作,但我遇到的最后一件事是处理 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
}
Run Code Online (Sandbox Code Playgroud)

除了服务器 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
}
Run Code Online (Sandbox Code Playgroud)

这在 Core 中运行时效果很好。但是在桌面上运行时,出现错误Unable to find type [Microsoft.PowerShell.Commands.HttpResponseException]

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

bri*_*ist 5

我可能建议您在执行异常处理的 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
}
Run Code Online (Sandbox Code Playgroud)

这需要大量的工作(正确解析异常,也许制作 2 个以上的变体,确定您所在的平台是真实的还是$PSversionTable.Is51.Is6X真实的,创建您自己的异常类,创建它的适当实例投射$_到它等)。

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