5

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..!

rangi
  • 361
  • 2
  • 4
  • 21

1 Answers1

9

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;
}
Mark Wragg
  • 22,105
  • 7
  • 39
  • 68
  • 1
    you're a genius, mate! Well spotted and I've gone with the "If" blocks and ToString() because I'm logging results in SQL server. Many Thanks :o) – rangi Jul 04 '17 at 07:31
  • When using Set-StrictMode -Version 2.0, this results in the error message: "The property 'StatusCode' cannot be found on this object. Verify that the property exists." – Bernard Vander Beken Oct 18 '18 at 08:17
  • @BernardVanderBeken I had this with 'Response' because `Invoke-Webrequest` threw an error before even trying to make the connection. To work around this encapsulate this solution between `Set-StrictMode -Off` (or `Set-StrictMode -Version 1.0`) and `Set-StrictMode -Version Latest`. But be aware that you won't be alerted to PowerShell API changes. – Farway Jul 12 '19 at 10:04
  • 3
    @BernardVanderBeken even better: Set the error type of at the catch statement (as done in the question): `catch [System.Net.WebException] { ...` – Farway Jul 12 '19 at 10:16