admin管理员组

文章数量:1302273

Our build system uses pwsh (Powershell 7.4.0) to execute a load of commands to build and test our software. We recently encountered a problem where something like the following example launched our test harness in a new window resulting in our tests appearing to pass instead of fail. Why is there a difference between these two and how could we harden things (other than removing the space)?

This one silently failes as it appear to launch the test

PS C:\Temp>& "${Env:NUNIT_LOCATION}\nunit-console-x86.exe " CodeUnderTest.dll
PS C:\Temp>$LastExitCode
0

This one works as expected and reports failures on the command line (and modifies the return code):

PS C:\Temp>& "${Env:NUNIT_LOCATION}\nunit-console-x86.exe" CodeUnderTest.dll

<test error outputs here>

PS C:\Temp>$LastExitCode
35

Our build system uses pwsh (Powershell 7.4.0) to execute a load of commands to build and test our software. We recently encountered a problem where something like the following example launched our test harness in a new window resulting in our tests appearing to pass instead of fail. Why is there a difference between these two and how could we harden things (other than removing the space)?

This one silently failes as it appear to launch the test

PS C:\Temp>& "${Env:NUNIT_LOCATION}\nunit-console-x86.exe " CodeUnderTest.dll
PS C:\Temp>$LastExitCode
0

This one works as expected and reports failures on the command line (and modifies the return code):

PS C:\Temp>& "${Env:NUNIT_LOCATION}\nunit-console-x86.exe" CodeUnderTest.dll

<test error outputs here>

PS C:\Temp>$LastExitCode
35
Share asked Feb 10 at 14:31 Jon CageJon Cage 37.5k41 gold badges147 silver badges224 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

You're seeing what is arguably a bug, present in both Windows PowerShell (the legacy, ships-with-Windows, Windows-only edition of PowerShell whose latest and last version is 5.1) and PowerShell (Core) 7 (the modern, cross-platform, install-on-demand edition) as of 7.5.0:[1]

  • With the trailing space in the path, PowerShell doesn't recognize the executable as an executable (application).

  • Instead, it treats it like a document and therefore performs the equivalent of a Start-Process call[2] in order to delegate the invocation to the Windows (GUI) shell, which has two implications:

    • The console application you're trying to launch opens in a new console window that automatically closes when the application exits.

    • It launches asynchronously, and therefore its exit code is not captured in the automatic $LASTEXITCODE variable, so whatever $LASTEXITCODE was previously in effect remains in effect.


how could we harden things

Short of writing a generic wrapper function that trims trailing spaces from the executable path, you can perform trimming ad hoc; e.g.:

$exePath = "${Env:NUNIT_LOCATION}\nunit-console-x86.exe "

& $exePath.Trim() CodeUnderTest.dll

[1] The bug has been reported in GitHub issue #24990.

[2] Start-Process can be made to act synchronously with the -Wait switch, and the -PassThru switch can be used to make the call output a System.Diagnostics.Process instance whose .ExitCode property can then be queried, but note that, except in unusual scenarios, there is no good reason to use Start-Process for executing console applications, not least because you won't be able to directly capture their output. See this answer for more information.

本文标签: