Friday, 19 September 2014

Beware of Invoke-WebRequest in PowerShell DSC

PowerShell has a handy cmdlet named Invoke-WebRequest. I was making use of this in a Script resource as part of a DSC script.

The weird thing was that most of the time it worked, but sometimes the DSC script hung, and as best I could tell, it was within the Script resource that was calling Invoke-WebRequest, but I couldn’t understand why.

Eventually on one particular server, I was able to cause something surprising to happen – calling Invoke-WebRequest caused a modal dialog to appear. The interesting thing was that the server had Internet Explorer Enhanced Security Configuration enabled. Not surprisingly that’s the default for Windows Server.

I posted a question to Stack Overflow and a comment added to the answer made me realise what is actually going on.

I had naively assumed that Invoke-WebRequest is just a nice wrapper around the .NET Framework’s WebClient class, but it turns out it is a bit more than that. It also appears to reference IE-related code.

If you're curious as to what Invoke-WebRequest actually does, then fire up your favourite IL decompiler and point it at C:\Windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.PowerShell.Commands.Utility\v4.0_3.0.0.0__31bf3856ad364e35\Microsoft.PowerShell.Commands.Utility.dll (that's the path I found the full assembly at).

While the implementation of Invoke-WebRequest actually uses System.Net.WebRequest, it also creates an instance of the IHTMLDocument2 COM object, and I suspect this is the trigger that causes the IE warning to appear.

So if you just want to hit a web address without requiring all the extra features of IE processing, just call either WebClient or WebRequest directly from PowerShell, or Use Invoke-WebRequest but probably not in a 'headless' environment.

No comments: