Obtaining ExitCode using Start-Process and WaitForExit instead of -Wait

后端 未结 6 1009
一生所求
一生所求 2020-11-29 01:29

I\'m trying to run a program from PowerShell, wait for the exit, then get access to the ExitCode, but I am not having much luck. I don\'t want to use -Wait with

相关标签:
6条回答
  • 2020-11-29 02:10

    Here's a variation on this theme. I want to uninstall Cisco Amp, wait, and get the exit code. But the uninstall program starts a second program called "un_a" and exits. With this code, I can wait for un_a to finish and get the exit code of it, which is 3010 for "needs reboot". This is actually inside a .bat file.

    If you've ever wanted to uninstall folding@home, it works in a similar way.

    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
    
    0 讨论(0)
  • 2020-11-29 02:11

    Or try adding this...

    $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)
    

    By using this code, you can still let PowerShell take care of managing redirected output/error streams, which you cannot do using System.Diagnostics.Process.Start() directly.

    0 讨论(0)
  • 2020-11-29 02:16

    The '-Wait' option seemed to block for me even though my process had finished.

    I tried Adrian's solution and it works. But I used Wait-Process instead of relying on a side effect of retrieving the process handle.

    So:

    $proc = Start-Process $msbuild -PassThru
    Wait-Process -InputObject $proc
    
    if ($proc.ExitCode -ne 0) {
        Write-Warning "$_ exited with status code $($proc.ExitCode)"
    }
    
    0 讨论(0)
  • 2020-11-29 02:24

    There are two things to remember here. One is to add the -PassThru argument and two is to add the -Wait argument. You need to add the wait argument because of this defect: 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.
    

    Once you do this a process object is passed back and you can look at the ExitCode property of that object. Here is an example:

    $process = start-process ping.exe -windowstyle Hidden -ArgumentList "-n 1 -w 127.0.0.1" -PassThru -Wait
    $process.ExitCode
    
    # This will print 1
    

    If you run it without -PassThru or -Wait, it will print out nothing.

    The same answer is here: How do I run a Windows installer and get a succeed/fail value in PowerShell?

    0 讨论(0)
  • 2020-11-29 02:26

    Two things you could do I think...

    1. Create the System.Diagnostics.Process object manually and bypass Start-Process
    2. Run the executable in a background job (only for non-interactive processes!)

    Here's how you could do either:

    $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
    

    OR

    Start-Job -Name DoSomething -ScriptBlock {
        & ping.exe somehost
        Write-Output $LASTEXITCODE
    }
    #Do other stuff here
    Get-Job -Name DoSomething | Wait-Job | Receive-Job
    
    0 讨论(0)
  • 2020-11-29 02:27

    While trying out the final suggestion above, I discovered an even simpler solution. All I had to do was cache the process handle. As soon as I did that, $process.ExitCode worked correctly. If I didn't cache the process handle, $process.ExitCode was null.

    example:

    $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)"
    }
    
    0 讨论(0)
提交回复
热议问题