使用 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
并在整个代码中使用它。它将使事情更易于管理。
我有一个针对 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
并在整个代码中使用它。它将使事情更易于管理。