23 Feb 2012

Calling Executable Files in PowerShell

I was called out on my approach on this in work today, so I thought I would share my thoughts on this topic.  The actual executable concerned was STSADM command line tool for SharePoint 2010 (yes, STSADM is still useful in SharePoint 2010, for example in enabling self-service site creation). Unfortunately, I don’t have STSADM installed on the machine I’m writing this blog post on, so I use the example of calling Internet Explorer instead. The principal is the same in both cases.

To call Internet Explorer from the command line, you would use the following command:

C:\Program Files\Internet Explorer\iexplore.exe

But if you try and run the above command in PowerShell, you will get the following error:

PowerShell Error

To correct the error, we need to enclose the path to the iexplore.exe file in quotes:

“C:\Program Files\Internet Explorer\iexplore.exe”

But this will not actually result in IE being called; this is because PowerShell treats the input as a string, and will simply write the text enclosed in the quotes to the console.  To run the string as a script whose path is enclosed in quotes, you preface the string with the call operator (ampersand):

& “C:\Program Files\Internet Explorer\iexplore.exe”

Alternatively, we can use the Invoke-Item cmdlet:

Invoke-Item “C:\Program Files\Internet Explorer\iexplore.exe”

And both approaches will successfully start an instance of Internet Explorer.  Alternatively, you could break the statement into two:

CD “C:\Program Files\Internet Explorer\”

Which would also work.  Note, if you needed to return to the original directory from which the PowerShell script was called, you could do so using the following code:

Push-Location “C:\Program Files\Internet Explorer\”

The cmdlet Push-Location is virtually identical to the CD command; however, it saves your previous location before moving to a new one.

So, can we now specify at the PowerShell prompt the URL that IE opens with? The command line switch information for IE tells us that we can, by adding an additional parameter:

& “C:\Program Files\Internet Explorer\iexplore.exe” http://www.bbc.co.uk/news/

And again, this successfully works.  Can we now call IE with several parameters?

& “C:\Program Files\Internet Explorer\iexplore.exe” http://www.bbc.co.uk/news/ –private

And this PowerShell statement will call Internet Explorer so that it opens at the BBC News site in p0rn InPrivate mode.  So that we can see that to call STSADM from PowerShell, we could use the following command:

& “C:\Program Files\Common Files\Microsoft Shared\Web server extensions\14\bin\stsadm.exe” -o enablessc -url http://myserver –requiresecondarycontact

And this would work.  Except, of course, that no self respecting software developer would leave should a horribly long line of code in a script.  They would refactor this line of code by using an alias for the STSADM executable, and so avoid having to repeatedly use a hard-coded literal for the executable path.  They would also realise that the location of the common programs varies according to how Windows itself was installed on the target computer, and make use of the %CommonProgramFiles% environment variable:

set-alias STSADM "${env:commonprogramfiles}\Microsoft Shared\Web Server Extensions\14\BIN\STSADM.EXE"
$serverUrl = http://myserver
STSADM –o enablessc –url $serverUrl –requiresecondarycontact

The above code is now more easily read and maintained.  If you want to investigate further how PowerShell parses quotes, etc., check out this StackOverFlow question, and Keith Hill’s answer:

1 comment:

  1. To my shame I didn't actually realise that PowerShell existed until your posts. Still, new lesson learned. As you know I'm more of a Linux user these days but I'll definitely give it a look. Cheers for the tip.