Pregunta

Tengo un servicio de Windows escrito en Delphi que ejecuta varios programas.

Al detener el servicio, también quiero cerrar estos programas. Cuando el servicio se escribió originalmente, funcionó bien, pero creo que actualicé el componente tProcess y ahora: los programas subordinados no se están cerrando.

en tProcess: aquí está el código que inicia los nuevos procesos.

  if CreateProcess( nil , PChar( FProcess.Command ) , nil , nil , False ,
    NORMAL_PRIORITY_CLASS , nil , Directory ,
    StartupInfo , ProcessInfo ) then
    begin
      if FProcess.Wait then
        begin
          WaitForSingleObject( ProcessInfo.hProcess , Infinite );
          GetExitCodeProcess( ProcessInfo.hProcess , ExitCode );
          if Assigned( FProcess.FOnFinished ) then
            FProcess.FOnFinished( FProcess , ExitCode );
        end;
      CloseHandle( ProcessInfo.hProcess );
      CloseHandle( ProcessInfo.hThread );
    end;

Cada uno de los ejecutables llamados por esto son Programas GUI de Windows (con un botón de cierre en la parte superior)

Cuando detengo el servicio, también quiero detener (no eliminar) los programas que inicié mediante el procedimiento createProcess.

¿Cómo harías esto?

¿Fue útil?

Solución

Desea enumerar las ventanas abiertas que coinciden con su ProcessId lanzado y decirles que se cierren. Aquí hay un código de muestra para eso:

uses Windows;

interface   

function MyTerminateAppEnum(hHwnd:HWND; dwData:LPARAM):Boolean; stdcall;

implementation

function MyTerminateAppEnum(hHwnd:HWND; dwData:LPARAM):Boolean; 
var   
  vID:DWORD; 
begin   
  GetWindowThreadProcessID(hHwnd, @vID);   
  if vID = dwData then   
  begin
    PostMessage(hHwnd, WM_CLOSE, 0, 0); //tell window to close gracefully
    Result := False;  //can stop enumerating    
  end   
  else   
  begin
    Result := TRUE;  //keep enumerating until you find your id   
  end; 
end;

Entonces querrá utilizar esto en su código cuando quiera cerrar las aplicaciones iniciadas:

Procedure TerminateMe(YourSavedProcessInfo:TProcessInformation);
var
  vExitCode:UINT;
begin
  GetExitCodeProcess(YourSavedProcessInfo.hProcess, vExitCode);
  if (vExitCode = STILL_ACTIVE) then  //launched app still running..
  begin
    //tell it to close
    EnumWindows(@MyTerminateAppEnum, YourSavedProcessInfo.dwProcessId);

    if WaitForSingleObject(YourSavedProcessInfo.hProcess, TIMEOUT_VAL) <> WAIT_OBJECT_0 then
    begin
      if not TerminateProcess(YourSavedProcessInfo.hProcess, 0) then  //didn't close, try to terminate
      begin
         //uh-oh   Didn't close, didn't terminate..
      end;
    end;
  end;
  CloseHandle(YourSavedProcessInfo.hProcess);
  CloseHandle(YourSavedProcessInfo.hThread);
end;

Otros consejos

Usaría el componente TJvCreateProcess de JVCL que envuelve cualquier proceso funcionalidad relacionada de win32 de una manera elegante. Esta respuesta proviene del departamento de no toque-winapi-a menos que sea realmente necesario :-)

La única forma genérica de detener un proceso es usar TerminateProcess . Pero eso está tan lejos de ser elegante como puedas. Para cerrar un proceso con gracia, debe decirle al proceso que desea que se detenga y luego esperar que obedezca. Sin embargo, no hay forma de hacerlo en general.

Para un programa GUI, la forma habitual de decirle que desea que deje de ejecutarse es cerrar su ventana principal. No hay una idea formal de "ventana principal". aunque. Un programa puede tener cero o más ventanas, y no hay forma de saber externamente cuál se supone que debes cerrar para que el programa deje de funcionar.

Puede usar EnumWindows para recorrer todas las ventanas y seleccione los que pertenecen a su proceso. (Serían aquellos para los que GetWindowThreadProcessId ofrece el mismo proceso ID que CreateProcess le dio.)

Cerrar una ventana puede no ser suficiente. El programa puede mostrar un cuadro de diálogo (solicitando confirmación o solicitando guardar cambios, etc.). Debería saber de antemano cómo descartar ese cuadro de diálogo.

Los programas que no son GUI pueden tener problemas similares. Puede ser suficiente simular una combinación de teclas Ctrl + C. Sin embargo, podría atrapar y manejar esa pulsación de tecla de manera diferente. Es posible que tenga un sistema de menús que espere que escriba " Q " para salir del programa.

En resumen, no puede cerrar con gracia un programa a menos que sepa de antemano cómo espera que se cierre ese programa.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top