Powershell handling of System.Net.WebException

rangi picture rangi · Jul 4, 2017 · Viewed 9.1k times · Source

Having almost mastered using Powershell Invoke-WebRequest I'm now embarking on trying to get control of exception errors

In this first piece of code I've got to handle the exceptions returned from the web service ok. You can see a 400 code is returned along with a Message description and a detailed message.

Try {
    $what = Invoke-WebRequest -Uri $GOODURL -Method Post -Body $RequestBody -ContentType $ContentType
}

catch [System.Net.WebException] {
    $Request = $_.Exception
    Write-host "Exception caught: $Request"

    $crap = ($_.Exception.Response.StatusCode.value__ ).ToString().Trim();
    Write-Output $crap;
    $crapMessage = ($_.Exception.Message).ToString().Trim();
    Write-Output $crapMessage;
    $crapdescription = ($_.ErrorDetails.Message).ToString().Trim();
    Write-Output $crapdescription;
 }

Output returned. Nice!

Exception caught: System.Net.WebException: The remote server returned an error: (400) Bad Request.
   at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.GetResponse(WebRequest request)
   at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.ProcessRecord()
   400
   The remote server returned an error: (400) Bad Request.
   Modus.queueFailed Could not queue message http://schemas.xmlsoap.org/soap/actor/next

That's very cool, however as part of my testing I wanted simulate connection errors, so I fed the script an invalid URI and immediately my error handling in the above code crashed.

Specifically, the invalid URI fell over on the "$_.Exception.Response.StatusCode.value__" and "$_.ErrorDetails.Message" presumably because they don't exist in the System.Net.WebException object returned

So, I took them out as a test and sure enough it works with the invalid URL as expected as below

Try {
    $what = Invoke-WebRequest -Uri $BADURL -Method Post -Body $RequestBody -ContentType $ContentType
}

catch [System.Net.WebException] {
    $Request = $_.Exception
    Write-host "Exception caught: $Request"

    $crapMessage = ($_.Exception.Message).ToString().Trim();
    Write-Output $crapMessage;
 }

And I get this (also nice)

Exception caught: System.Net.WebException: The remote name could not be resolved: 'gateway.zzzzsonicmobile.com'
   at System.Net.HttpWebRequest.GetRequestStream(TransportContext& context)
   at System.Net.HttpWebRequest.GetRequestStream()
   at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.SetRequestContent(WebRequest request, String content)
   at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.ProcessRecord()
   at System.Management.Automation.CommandProcessor.ProcessRecord()

   The remote name could not be resolved: 'gateway.zzzzsonybile.com'

Trouble is, the first example gets everything I want from the exception object but won't work with an invalid URL. The second example handles the invalid URL (connection errors), but I can't figure out how to get hold of the 400 StatusCode and the ErrorDetails.Message

I would really like to do that, if at all possible.

Is there a way of setting this up to handle all exception handling..?

Any help, much appreciated..!

Answer

Mark Wragg picture Mark Wragg · Jul 4, 2017

I think you're probably only seeing an issue because you're trying to do the .ToString().Trim() methods on those properties when they don't exist. I'm not sure doing those methods even adds a lot of value, so I'd be tempted to just remove them.

Alternatively, you could put If blocks around them so that they are only output if they have value:

If ($_.Exception.Response.StatusCode.value__) {
    $crap = ($_.Exception.Response.StatusCode.value__ ).ToString().Trim();
    Write-Output $crap;
}
If  ($_.Exception.Message) {
    $crapMessage = ($_.Exception.Message).ToString().Trim();
    Write-Output $crapMessage;
}