0

Assume I have two files, script.ps1 and filename.cmd, and I run .\script.ps1 from a Powershell prompt:

script.ps1

Write-Host "About to run filename.cmd"
$proc = Start-Process -FilePath filename.cmd -NoNewWindow -Wait
Write-Host "proc: [$proc]"
Write-Host "LASTEXITCODE: [$LASTEXITCODE]

filename.cmd

@echo off
ECHO File returns ErrorLevel=1
exit /b 1

Output:

About to run filename.cmd
proc: []
LASTEXITCODE: []

Both proc and LASTEXITCODE are $null. My understanding was that somehow I could access the ErrorCode?

How do I read the failed error level (in this case 1) in my Powershell script?

1 Answer 1

0

To synchronously execute console applications, including batch files, call them directly, do not use Start-Process - see this answer.

Therefore:

Write-Host "About to run filename.cmd"
# For security reasons, PowerShell requires that you explicitly
# signal the intent to run an executable located *in the current directory*,
# hence the need for `./` (or `.\`)
# Only direct invocation of external programs (batch files) sets
# the automatic $LASTEXITCODE variable.
./filename.cmd
Write-Host "LASTEXITCODE: [$LASTEXITCODE]

As for what you tried:

Start-Process outputs nothing by default - except if you pass the -PassThru switch, in which case a System.Diagnostics.Process instance representing the newly started process is returned.

Assuming you've also specified -Wait, as in your case, you can then access the returned object's .ExitCode property to determine the exit code immediately afterwards.

Note that automatic variable $LASTEXITCODE is only set after direct invocation of external programs, as shown above.

Therefore, if you were to use Start-Process - which is not necessary in this case, as explained above - you'd have to use the following:

Write-Host "About to run filename.cmd"
$proc = Start-Process -PassThru -FilePath filename.cmd -NoNewWindow -Wait
Write-Host "proc: [$proc]"
Write-Host "exit coe: [$($proc.ExitCode)]
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks this is very helpful. I ended up using Invoke-Expression -Command "filename.cmd" | Out-Host so that I could mock the call in my Pester tests, which appears to have worked like a charm using $LASTEXITCODE
Glad to hear it, @satoukum. As a matter of habit, I suggest avoiding Invoke-Expression, so perhaps Invoke-Command { ./filename.cmd } is the better alternative.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.