2011-03-10 12 views
8

estoy tratando de iniciar una aplicación externa con estatus elevado, y esperar hasta que salga antes de continuar:¿Cómo uso correctamente el método WaitForSingleObject para esperar a que termine un programa externo?

var 
    FProcess: THandle; 
    ExecInfo: TShellExecuteInfo; 
begin 

    FillChar(ExecInfo, SizeOf(ExecInfo), 0); 
    with ExecInfo do 
    begin 
    cbSize := SizeOf(ExecInfo); 
    fMask := 0; 
    Wnd := AWindow; 
    lpVerb := 'runas'; 
    lpFile := PChar(APath); 
    lpParameters := PChar(AParams); 
    lpDirectory := PChar(AWorkDir); 
    nShow := SW_NORMAL; 
    end; 

    Result := ShellExecuteEx(@ExecInfo); 

    if Wait then 
    begin 
    while WaitForSingleObject(ExecInfo.hProcess, INFINITE) <> WAIT_TIMEOUT do 
     Application.ProcessMessages; 
    end; 

Esta lanza, pero sólo sigue esperando. El programa que llama nunca continúa después de la llamada a WaitForSingleObject, incluso después de que el programa llamado sale.

He intentado WAIT_OBJECT_0 en lugar de WAIT_TIMEOUT, pero tengo el mismo problema. ¿Qué estoy haciendo mal aquí?

+1

¿Qué proceso ¿Está intentando ejecutar? ¿Estás seguro de que tuvo éxito? Si lo hizo, ¿está seguro de que tiene un identificador válido? Hay muchas cosas que podrían salir mal en ese código antes de llegar a la parte sobre la que pregunta. Asegúrate de preguntar sobre lo correcto. Y si la llamada WaitForSingleObject regresa, claramente no está devolviendo Wait_Timeout; entonces, ¿qué * está * volviendo? –

Respuesta

11

lo que se supone el código

while WaitForSingleObject(ExecInfo.hProcess, INFINITE) <> WAIT_TIMEOUT do 
    Application.ProcessMessages; 

hacer? Es un ciclo infinito.

Uso simplemente

WaitForSingleObject(ExecInfo.hProcess, INFINITE); 

lugar. Y sí, necesita

fMask:= SEE_MASK_NOCLOSEPROCESS; 

para obtener el identificador del proceso.

2

Si lee description of ShellExecuteEx in MSDN, verá esto:

hProcess

Type: HANDLE 

un identificador de la aplicación recién comenzado. Este miembro está configurado en return y siempre es NULL a menos que fMask esté establecido en SEE_MASK_NOCLOSEPROCESS. Incluso si fMask está configurado en SEE_MASK_NOCLOSEPROCESS, hProcess será será NULL si no se inició ningún proceso.

I.e. simplemente no tiene un mango válido. Debe configurar fMask como se indica arriba.

+0

Eso no funcionó para mí. Después de cambiar el fMask en consecuencia, todavía bloquea la aplicación de llamada. – croceldon

4

Su código está roto. No está pasando la bandera SEE_MASK_NOCLOSEPROCESS al ShellExecuteEx(), por lo que no le devolverá un identificador de proceso válido, y su ciclo ignorará los errores que WaitForSingleObject() le indica por eso, por lo que termina en un ciclo sin fin.

probar este lugar:

var 
    ExecInfo: TShellExecuteInfo; 
begin 
    ZeroMemory(@ExecInfo, SizeOf(ExecInfo)); 
    with ExecInfo do 
    begin 
    cbSize := SizeOf(ExecInfo); 
    fMask := SEE_MASK_NOCLOSEPROCESS; 
    Wnd := AWindow; 
    lpVerb := 'runas'; 
    lpFile := PChar(APath); 
    lpParameters := PChar(AParams); 
    lpDirectory := PChar(AWorkDir); 
    nShow := SW_NORMAL; 
    end; 
    Result := ShellExecuteEx(@ExecInfo); 
    if Result and Wait then 
    begin 
    if ExecInfo.hProcess <> 0 then // no handle if the process was activated by DDE 
    begin 
     repeat 
     if MsgWaitForMultipleObjects(1, ExecInfo.hProcess, FALSE, INFINITE, QS_ALLINPUT) = (WAIT_OBJECT_0+1) then 
      Application.ProcessMessages 
     else 
      Break; 
     until False; 
     CloseHandle(ExecInfo.hProcess); 
    end; 
    end; 
end; 
+0

¿Cómo se obtiene el 'ExitCode' del proceso llamado con este método? –

+0

Llame ['GetExitCodeProcess()'] (http://msdn.microsoft.com/en-us/library/windows/desktop/ms683189.aspx) después de que el bucle finalice y antes de cerrar el manejador del proceso. –

Cuestiones relacionadas