I can't figure out the syntax for this, I have a config script that needs to be called from another script. When I call the config script manually, it looks like this config.ps1 -val1 "1234" -val2 "12.089"
. I need to use Start-Process to call config.ps1 with the parameters as well as to not open a new window (non interactive) and to capture the exit code of config.ps1 and wait for it to return an exit code before proceeding further.
Here is what I've tried most recently
$process = Start-Process powershell.exe -FilePath "c:\config.ps1" -ArgumentList -val1 "1234" -val2 "12.089" -PassThru -WindowStyle Hidden -Wait;
Building on Daniel's helpful comments.
The problem with your code:
$process = Start-Process powershell.exe -FilePath "c:\config.ps1" -ArgumentList -val1 "1234" -val2 "12.089" -PassThru -WindowStyle Hidden -Wait
You're invoking powershell.exe
, which therefore needs to be the argument passed to Start-Process
's -FilePath
parameter.
Everything else - both the target PowerShell script, c:\config.ps1
and its arguments - must be passed to the -ArgumentList
parameter, which is best done in the form of a single string with embedded quoting, if necessary.[1]
Thus, the immediate fix is (-WindowStyle Hidden
omitted for brevity; note the addition of -File
and the use of a verbatim here-string (@'<newline>...<newline>'@
) to simplify embedded quoting):
$process =
Start-Process -PassThru -Wait -FilePath powershell.exe -ArgumentList @'
-File "c:\config.ps1" -val1 "1234" -val2 "12.089"
'@
Note that while in this particular case omitting the -File
parameter of powershell.exe
, the Windows PowerShell CLI, would have worked in principle too - in which case -Command
is implied, there is an important difference:
-File
passes a script file's exit code through as the exit code of the powershell.exe
process, whereas -Command
reports only an abstract exit code: any nonzero exit code is mapped onto 1
.[2]-File
and -Command
.[3]$process.ExitCode
then reflects the script's exit code.
Taking a step back:
Normally, you'd invoke a PowerShell script (*.ps1
file) in-process, by direct invocation, which is invariably synchronous (i.e., PowerShell waits for the script to terminate before continuing):
# Direct, in-process invocation.
# * If the script path must be quoted or is stored in a variable,
# use &, the call operator (e.g., & "c:\config.ps1" ...)
# * If the script uses `exit` with a number to set an exit code, that
# it will be reflected in $LASTEXITCODE.
c:\config.ps1 -val1 1234 -val2 12.089
If you do need process isolation or if you must make a cross-edition call, e.g., calling powershell.exe
, the Windows PowerShell CLI, from a PowerShell (Core) 7 session, using direct invocation for the CLI call too is the simpler solution for a synchronous call, which too allows you to query the exit code via the automatic $LASTEXITCODE
variable.
powershell.exe -File c:\config.ps1 -val1 1234 -val2 12.089
Note:
Your Start-Process
call uses -WindowStyle Hidden
and therefore hides any output produced by the script; if you similarly want to hide all output in direct invocation, append *>$null
to the commands above.
Conversely, the direct-invocation technique allows you to capture the command's output, e.g.
$output = powershell.exe -File c:\config.ps1 -val1 1234 -val2 12.089
2>
redirection, you can selectively capture error output in a file.[1] See this answer for more information.
[2] See this answer for more information.
[3] See this answer for more information.
[4] See GitHub issue #7989 for a discussion of this problematic behavior.