Obtaining ExitCode using Start-Process and WaitForExit instead of -Wait
我正在尝试从PowerShell运行程序,等待退出,然后获得对ExitCode的访问权限,但运气不佳。 我不想将
这是一个简化的测试脚本:
1 2 3 4 5 6 7 8 9 10 11 12 | cd"C:\Windows" # ExitCode is available when using -Wait... Write-Host"Starting Notepad with -Wait - return code will be available" $process = (Start-Process -FilePath"notepad.exe" -PassThru -Wait) Write-Host"Process finished with return code:" $process.ExitCode # ExitCode is not available when waiting separately Write-Host"Starting Notepad without -Wait - return code will NOT be available" $process = (Start-Process -FilePath"notepad.exe" -PassThru) $process.WaitForExit() Write-Host"Process exit code should be here:" $process.ExitCode |
运行此脚本将导致记事本启动。 手动关闭后,将打印退出代码,并且无需使用
1 2 3 4 | Starting Notepad with -Wait - return code will be available Process finished with return code: 0 Starting Notepad without -Wait - return code will NOT be available Process exit code should be here: |
我需要能够在启动程序与等待程序退出之间执行其他处理,因此无法使用
这里有两件事要记住。一种是添加
1 2 3 | -PassThru [<SwitchParameter>] Returns a process object for each process that the cmdlet started. By d efault, this cmdlet does not generate any output. |
完成此操作后,将回传一个过程对象,您可以查看该对象的ExitCode属性。这是一个例子:
1 2 3 4 | $process = start-process ping.exe -windowstyle Hidden -ArgumentList"-n 1 -w 127.0.0.1" -PassThru -Wait $process.ExitCode # This will print 1 |
如果在没有
相同的答案在这里:如何运行Windows安装程序并在PowerShell中获取成功/失败值?
我认为您可以做两件事...
您可以按照以下方式进行操作:
1 2 3 4 5 6 7 8 9 10 11 12 | $pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName ="notepad.exe" $pinfo.RedirectStandardError = $true $pinfo.RedirectStandardOutput = $true $pinfo.UseShellExecute = $false $pinfo.Arguments ="" $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo $p.Start() | Out-Null #Do Other Stuff Here.... $p.WaitForExit() $p.ExitCode |
要么
1 2 3 4 5 6 | Start-Job -Name DoSomething -ScriptBlock { & ping.exe somehost Write-Output $LASTEXITCODE } #Do other stuff here Get-Job -Name DoSomething | Wait-Job | Receive-Job |
在尝试上述最终建议时,我发现了一个更简单的解决方案。我要做的就是缓存进程句柄。我这样做后,$ process.ExitCode便可以正常工作。如果未缓存进程句柄,则$ process.ExitCode为null。
例:
1 2 3 4 5 6 7 | $proc = Start-Process $msbuild -PassThru $handle = $proc.Handle # cache proc.Handle $proc.WaitForExit(); if ($proc.ExitCode -ne 0) { Write-Warning"$_ exited with status code $($proc.ExitCode)" } |
即使我的过程已完成,"-等待"选项似乎也对我不利。
我尝试了阿德里安的解决方案,它可以工作。但是我使用Wait-Process而不是依赖于检索过程句柄的副作用。
所以:
1 2 3 4 5 6 | $proc = Start-Process $msbuild -PassThru Wait-Process -InputObject $proc if ($proc.ExitCode -ne 0) { Write-Warning"$_ exited with status code $($proc.ExitCode)" } |
或尝试添加此...
1 2 3 4 5 6 7 | $code = @" [DllImport("kernel32.dll")] public static extern int GetExitCodeProcess(IntPtr hProcess, out Int32 exitcode); "@ $type = Add-Type -MemberDefinition $code -Name"Win32" -Namespace Win32 -PassThru [Int32]$exitCode = 0 $type::GetExitCodeProcess($process.Handle, [ref]$exitCode) |
通过使用此代码,您仍然可以让PowerShell负责管理重定向的输出/错误流,而直接使用System.Diagnostics.Process.Start()则无法做到。