我正在尝试从PowerShell运行程序,等待退出,然后访问ExitCode,但我没有太多运气。我不想将-Wait
与Start-Process
一起使用,因为我需要在后台进行一些处理。
这是一个简化的测试脚本:
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
运行此脚本将导致Notepad启动。手动关闭后,将打印退出代码,它将重新开始,而不使用-wait
。退出时不提供ExitCode:
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:
我需要能够在启动程序和等待它退出之间执行额外的处理,因此我无法使用-Wait
。我该怎么做,仍然可以访问此进程的.ExitCode属性?
答案 0 :(得分:79)
这里要记住两件事。一种是添加-PassThru
参数,另外两种是添加-Wait
参数。由于此缺陷,您需要添加wait参数:http://connect.microsoft.com/PowerShell/feedback/details/520554/start-process-does-not-return-exitcode-property
-PassThru [<SwitchParameter>]
Returns a process object for each process that the cmdlet started. By d
efault, this cmdlet does not generate any output.
执行此操作后,将传回一个进程对象,您可以查看该对象的ExitCode属性。这是一个例子:
$process = start-process ping.exe -windowstyle Hidden -ArgumentList "-n 1 -w 127.0.0.1" -PassThru -Wait
$process.ExitCode
# This will print 1
如果您在没有-PassThru
或-Wait
的情况下运行它,它将不打印任何内容。
答案如下: How do I run a Windows installer and get a succeed/fail value in PowerShell?
答案 1 :(得分:40)
我认为你可以做两件事......
以下是您可以这样做的方法:
$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
或强>
Start-Job -Name DoSomething -ScriptBlock {
& ping.exe somehost
Write-Output $LASTEXITCODE
}
#Do other stuff here
Get-Job -Name DoSomething | Wait-Job | Receive-Job
答案 2 :(得分:32)
在尝试上面的最终建议时,我发现了一个更简单的解决方案。我所要做的就是缓存进程句柄。一旦我这样做,$ process.ExitCode就能正常工作。如果我没有缓存进程句柄,$ process.ExitCode为null。
示例:
$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)"
}
答案 3 :(得分:8)
&#39; -Wait&#39;即使我的过程已经完成,选项似乎也阻止了我。
我尝试了Adrian的解决方案,但它确实有效。但我使用Wait-Process而不是依赖于检索进程句柄的副作用。
所以:
$proc = Start-Process $msbuild -PassThru
Wait-Process -InputObject $proc
if ($proc.ExitCode -ne 0) {
Write-Warning "$_ exited with status code $($proc.ExitCode)"
}
答案 4 :(得分:4)
或尝试添加此内容......
$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()。
答案 5 :(得分:0)
这是该主题的一种变体。我想卸载Cisco Amp,等待并获取退出代码。但是卸载程序会启动另一个名为“ un_a”的程序并退出。使用此代码,我可以等待un_a完成并获取它的退出代码,“需要重启”的退出代码为3010。这实际上是在.bat文件中。
如果您曾经想卸载folding @ home,它的工作方式与此类似。
rem uninstall cisco amp, probably needs a reboot after
rem runs Un_A.exe and exits
rem start /wait isn't useful
"c:\program files\Cisco\AMP\6.2.19\uninstall.exe" /S
powershell while (! ($proc = get-process Un_A -ea 0)) { sleep 1 }; $handle = $proc.handle; 'waiting'; wait-process Un_A; exit $proc.exitcode