捕获失败/401 Invoke-WebRequest 的响应

Tay*_*lor 5 powershell

当 Invoke-WebRequest 达到 500、401、403 等时,如何捕获输出?当调用成功时,它将结果存储在$Response变量中,但是如果我遇到 401,它会抛出错误但不存储响应。

$Response = Invoke-WebRequest -Method HEAD -Uri 'https://site.contoso.com'
Invoke-WebRequest : The remote server returned an error: (401) Unauthorized.
At line:1 char:13
+ $Response = Invoke-WebRequest -Method HEAD -Uri 'https://site.contoso.com' -Erro ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
Run Code Online (Sandbox Code Playgroud)

$Response变量仍然为空,但是端点返回 401 Unauthorized标头,它只是没有被 PowerShell 捕获,因为它将其视为异常。通过 Fiddler 进行管道传输证实了这一点。

创建使用请求[System.Net.WebRequest]具有当我执行相同的结果$Response = $WebRequest.GetResponse()

这是我的$PSVersionTable

Name                           Value                                                                                                           
----                           -----                                                                                                           
PSVersion                      4.0                                                                                                             
WSManStackVersion              3.0                                                                                                             
SerializationVersion           1.1.0.1                                                                                                         
CLRVersion                     4.0.30319.36373                                                                                                 
BuildVersion                   6.3.9600.16406                                                                                                  
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0}                                                                                            
PSRemotingProtocolVersion      2.2   
Run Code Online (Sandbox Code Playgroud)

Fox*_*loy 5

这实际上是GitHub 上 PowerShell 项目上的一个未解决的问题,但它可能有一天会得到解决。

现在,这是我们倾向于解决这个问题的方法。

首先,将此函数加载到内存中。

function Failure {
$global:helpme = $body
$global:helpmoref = $moref
$global:result = $_.Exception.Response.GetResponseStream()
$global:reader = New-Object System.IO.StreamReader($global:result)
$global:responseBody = $global:reader.ReadToEnd();
Write-Host -BackgroundColor:Black -ForegroundColor:Red "Status: A system exception was caught."
Write-Host -BackgroundColor:Black -ForegroundColor:Red $global:responsebody
Write-Host -BackgroundColor:Black -ForegroundColor:Red "The request body has been saved to `$global:helpme"
break
}
Run Code Online (Sandbox Code Playgroud)

然后,像这样包装您的 WebRequest。

try
{
    $Response = Invoke-WebRequest -Method HEAD -Uri 'https://site.contoso.com'
}
catch
{
    Failure
}
Run Code Online (Sandbox Code Playgroud)

这种方法很酷的一点是它编写了全局作用域变量,并且它们会在您的函数退出后持续存在。当您确实遇到错误时,只需在内部$global:result$global:responsebody完整错误中戳一下。

这是编写基于 RPC 或 REST 端点的模块时必须具备的。

这项技术归功于史蒂夫·沃尔。