Note:
tl;dr
Change the content of your PowerShell script (.ps1) to the following:
# Invoke sasoact.exe *synchronously*.
# Note: If sasoact.exe isn't a *console* application, append `| Write-Output`
& 'C:\Program Files\SASHome\SASFoundation\9.4\core\sasexe\sasoact.exe' action=Submit datatype=SASFile filename='C:\MyProject\test.sas' progid=SAS.Application.940
# Report its exit code.
exit $LASTEXITCODE
- Direct invocation of
sasoact.exe ensures synchronous execution and availability of its exit code via $LASTEXITCODE, which can be passed through with exit.
- This ensures that when your
process.WaitForExit(); call returns, both sasoact.exe and your PowerShell script have finished executing and that accessing process.ExitCode subsequently reflects sasoact.exe's exit code.
Your primary problem is that Start-Process launches a program asynchronously by default; while you can make the invocation synchronous with -Wait, there is no reason to use Start-Process to begin with - see next section. (If you still want to use it, pass both -Wait and -PassThru, and use exit with the .ExitCode property on the process-info object returned:
exit (
Start-Process -Wait -PassThru C:\Program Files\SASHome\SASFoundation\9.4\core\sasexe\sasoact.exe" -ArgumentList 'action=Submit datatype=SASFile filename="C:\MyProject\test.sas" progid=SAS.Application.940'
).ExitCode`
Typically, external executables that have CLIs are console applications, and, except in unusual circumstances, Start-Process is not the right way to invoke them.
- The unusual circumstances where
Start-Process is needed are: needing to run the program in a new console window (including with elevation) or needing to run with a different user identity. See here for guidance on when Start-Process is and isn't appropriate.
Invoking console applications directly has the following benefits:
synchronous invocation (whereas with Start-Process you'd have to use the -Wait switch) in the current console window (whereas Start-Process launches the process in a new window by default).[1]
the process exit code is reported in the automatic $LASTEXITCODE variable (with Start-Process, you'd have to use -Wait and -PassThru and query the .ExitCode property on the System.Diagnostics.Process instance that is returned)
the process' stdout and stderr streams are directly connected to PowerShell's output streams, allowing the output to be captured and redirected (whereas with Start-Process you can only redirect to files with -RedirectStandardOutput and -RedirectStandardError).
Note that even if the program being invoked isn't a console application, you can still force its synchronous execution and reflection of its exit code in $LASTEXITCODE by simply piping its direct invocation to | Write-Output - see this answer for more information.
[1] Given that Start-Process runs sasoact.exe in a new window by default, both powershell.exe and sasoact.exe will create a console window for themselves (assuming sasoact.exe is a console application). You can modify this behavior with the -WindowStyle parameter, but, as stated, unless you truly need to run in a separate window, there's no good reason to use Start-Process to begin with.