powershell - Obteniendo ExitCode usando Start-Process y WaitForExit en lugar de-Wait
powershell-v2.0 (5)
Al probar la sugerencia final anterior, descubrí una solución aún más simple. Todo lo que tuve que hacer fue almacenar en caché el identificador del proceso. Tan pronto como lo hice, $ process.ExitCode funcionó correctamente. Si no almacenaba en caché el identificador del proceso, $ process.ExitCode era nulo.
ejemplo:
$proc = Start-Process $msbuild -PassThru
$handle = $proc.Handle # cache proc.Handle http://stackoverflow.com/a/23797762/1479211
$proc.WaitForExit();
if ($proc.ExitCode -ne 0) {
Write-Warning "$_ exited with status code $($proc.ExitCode)"
}
Intento ejecutar un programa desde PowerShell, esperar la salida y acceder al código de salida, pero sin mucha suerte. No quiero usar -Espere con Start-Process, ya que necesito un procesamiento para continuar en segundo plano.
Aquí hay un script de prueba simplificado:
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
Al ejecutar este script, se iniciará el bloc de notas. Después de cerrar esto manualmente, se imprimirá el código de salida y se reiniciará sin usar -wait. No se proporciona ningún código de salida cuando esto se abandona:
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:
Necesito poder realizar un procesamiento adicional entre el inicio del programa y esperar a que se cierre, por lo que no puedo usar -Espera. ¿Alguna idea de cómo puedo hacer esto y aún tener acceso a la propiedad .ExitCode de este proceso?
Dos cosas que podrías hacer, creo ...
- Crear el objeto System.Diagnostics.Process manualmente y eludir el proceso de inicio
- Ejecute el ejecutable en un trabajo en segundo plano (¡solo para procesos no interactivos!)
Así es como podría hacer:
$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
O
Start-Job -Name DoSomething -ScriptBlock {
& ping.exe somehost
Write-Output $LASTEXITCODE
}
#Do other stuff here
Get-Job -Name DoSomething | Wait-Job | Receive-Job
Hay dos cosas para recordar aquí. Una es agregar el argumento -PassThru y dos es agregar el argumento -Espera. Debe agregar el argumento de espera debido a este defecto 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.
Una vez hecho esto, se pasa un objeto de proceso y se puede ver la propiedad ExitCode de ese objeto. Aquí hay un ejemplo:
$process = start-process ping.exe -windowstyle Hidden -ArgumentList "-n 1 -w 127.0.0.1" -PassThru -Wait
$process.ExitCode
# this will print 1
Si lo ejecuta sin -PassThru o -Wait, no imprimirá nada.
La misma respuesta aquí: https://.com/a/7109778/17822
La opción ''-Esperar'' pareció bloquearme a pesar de que mi proceso había terminado.
Probé la solución de Adrian y funciona. Pero utilicé Wait-Process lugar de confiar en un efecto secundario de recuperar el identificador del proceso.
Asi que:
$proc = Start-Process $msbuild -PassThru
Wait-Process -InputObject $proc
if ($proc.ExitCode -ne 0) {
Write-Warning "$_ exited with status code $($proc.ExitCode)"
}
O intenta agregar esto ...
$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)
Al usar este código, aún puede dejar que PowerShell se encargue de administrar flujos de salida / error redirigidos, lo que no puede hacer usando System.Diagnostics.Process.Start () directamente.