I am trying to write a wrapper script in Powershell which is passed the name of an executable, does some preprocessing, then invokes that executable with arguments resulting from that preprocessing. I want the executable to be anything you can run/open on Windows so I want to use Start-Process
to run it so Invoke a second script with arguments from a script (which references Invoke-Expression
) isn't really relevant. What I'm finding is that when the executable is another Powershell script, the arguments aren't seen by the script.
My stupid little test is:
Write-Output "Arg0: '$($Args[0])', Arg1: '$($Args[1])'" >>test.log
And working at a PS prompt this is what I see:
PS C:\Source> .\test.ps1 a b
PS C:\Source> more .\test.log
Arg0: 'a', Arg1: 'b'
PS C:\Source> .\test.ps1 c d
PS C:\Source> more .\test.log
Arg0: 'a', Arg1: 'b'
Arg0: 'c', Arg1: 'd'
PS C:\Source> Start-Process .\test.ps1 -ArgumentList e,f
PS C:\Source> Start-Process .\test.ps1 -Args e,f
PS C:\Source> more .\test.log
Arg0: 'a', Arg1: 'b'
Arg0: 'c', Arg1: 'd'
Arg0: '', Arg1: ''
Arg0: '', Arg1: ''
PS C:\Source>
Which is consistent with what I see when using Start-Process
in a script. I've spend a couple of hours Googling without finding an answer. Any thoughts?
I'm working on Windows 10 for development but my target is Windows Server. I don't know that that should make a difference.
You need to invoke the script through powershell.exe
:
Start-Process powershell -ArgumentList "-File .\test.ps1 arg1 arg2 argX"
You can specify the argument list either as a string or an array of strings. See example 7 here for more information.
As stated by @mklement0 in the question comment, if you don't invoke it through powershell.exe
, it will execute it in the default context as Windows thinks that .ps1
files should be executed, which does not pass additional arguments to the script in this case.
You may not need to use Start-Process
though - If you don't require any of the special functionality provided by Start-Process
you can also just call the script using the call &
operator or by specifying the path to the script just like you would interactively:
# You can use a variable with the path to the script
# in place of .\test.ps1 here and provide the arguments
# as variables as well, which lets you build a dynamic
# command out without using `Start-Process` or `Invoke-Expression`.
& .\test.ps1 arg1 arg2 argX
or
# You can use variables for the arguments here, but the script name
# must be hardcoded. Good for cases where the entrypoint doesn't change.
.\test.ps1 arg1 arg2 argX
You may also want to look into using argument splatting for your arguments as well when building out dynamic commands. I wrote an answer here as well which goes over splatting in more detail.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With