Passing arguments to a Powershell script caused me to pull my hair out... umm, scratch my head, lately. As with most technical problems, it appeared chaotic and intractable at first, and drew me into a black hole of spiraling confusion, where bugs mask other bugs; however, once I found a solution and tried to explain it to myself step-by-step, everything appeared orderly, even trivial. So now I don't even know why I'm writing this down. Actually, I do. It's so as not to go into the same black hole when I have to figure it again months or years from now.
It's easy to pass arguments to a Powershell script if you call it from the Powershell shell (pardon my inelegant expression). That's just
PS >./myScript "MyArgument"
What is more complicated is how to pass the arguments when invoking Powershell from DOS command shell, i.e. from
Suppose my script
myScript.ps1 is in the folder
I would invoke it as
powershell.exe -command "& C:\Users\elze\Documents\MyScripts\myScript.ps1"
where "&" is the command call operator.
Let's try to use Windows environmental variable
%userprofile%, which, in my case, is
powershell.exe -command "& %userprofile%\Documents\MyScripts\myScript.ps1"
myScript.ps1 is like this:
"My Output" | out-file $myArg -encoding UTF8
$myArg is an output file name. When we pass it to the script, we need to pass the whole path to it, otherwise Powershell will assume it is in the working directory, and the working directory may or may not be where our output file is located. Let's say the output file,
outputFile.txt is in the same directory as
cmd.exe was not invoked from this directory, the working directory will be something else.
How do you pass arguments to
myScript.ps1 from DOS command line?
Apparently, the straightforward way
powershell.exe -command "& %userprofile%\Documents\MyScripts\myScript.ps1 -myArg %userprofile%\Documents\MyScripts\outputFile.txt"
What if we have a space in the path? There is a good article on what to do about it (how to escape directory names and environmental variables) at http://www.tinyint.com/index.php/2011/04/20/escaping-quotes-in-powershel... .
Let's put our script in a folder called "Test Space". Clearly, the paths on the command line will have to be enclosed in quotes, otherwise they will be cut off after the space. Turns out, single quotes are enough, and Windows environmental variables still get expanded even when enclosed in single quotes:
powershell.exe -command "& '%userprofile%\Documents\MyScripts\Test Space\myScript.ps1' -myArg '%userprofile%\Documents\MyScripts\Test Space\outputFile.txt'"
Not so much when we use Powershell-style environmental variables, i.e.
powershell.exe -command "& '$env:userprofile\Documents\MyScripts\Test Space\myScript.ps1' -myArg '$env:userprofile\Documents\MyScripts\Test Space\output.txt'"
We'll get an error "The term
$env:userprofile\Documents\MyScripts\myScript.ps1 is not recognizeable as a script, cmdlet, etc."
In other words,
$env:userprofile did not get expanded. To expand it, we would probably need to do what TinyInt suggested. (If, however, we didn't put single quotes around the script and argument paths, the $env: variables would get expanded just fine.)
An interesting, and relevant to me, use case was when this Powershell command was invoked by Splunk Forwarder. The scripts invoked by Splunk Forwarder are stored in directories in
$SPLUNK_HOME path (e.g.
$SPLUNK_HOME is not a Windows environmental variable; apparently it's a Splunk environmental variable. The commands Splunk uses to invoke scripts are stored in files with extension .path. It looks for all the world like a DOS shell command, only it can also have Splunk environmental variables in it, such as
$SPLUNK_HOME. My guess is that Splunk Forwarder expands its environmental variables before it executes the command. So, for example, this works:
powershell.exe -command "& '$SPLUNK_HOME\bin\scripts\myScript.ps1' -myArg '$SPLUNK_HOME\bin\scripts\inputFile.txt'"
The single quotes that enclose the paths don't keep $SPLUNK_HOME from getting expanded. And they also serve to enclose a directory name with the space in it (such as Program Files).