Delphi - Anmutig Schließen Erstellt Prozess in Service. (Unter Verwendung von TProcess / Create)

StackOverflow https://stackoverflow.com/questions/268208

Frage

Ich habe einen Windows-Dienst in Delphi geschrieben, die eine Reihe von Programmen laufen.

Auf den Dienst stoppen, möchte ich auch diese Programme schließen. Wann wurde der Dienst ursprünglich geschrieben, arbeitete diese in Ordnung, aber ich glaube, ich die TProcess Komponente aktualisiert haben und nun - Die Unterprogramme werden nicht geschlossen.

in TProcess - Hier ist der Code, der die neuen Prozesse beginnt.

  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;

Jeder der ausführbaren Dateien durch diese aufgerufen sind Windows-GUI-Programme (mit einer Schließen-Schaltfläche am oberen Rand).

Wenn ich den Dienst zu beenden, möchte ich auch (nicht töten), die Programme stoppen ich über das Createprocess Verfahren habe in Betrieb genommen.

Wie würden Sie das tun?

War es hilfreich?

Lösung

Sie wollen offene Fenster aufzuzählen, die Ihren gestartet ProcessId entsprechen und die Fenster sagen zu schließen. Hier ist ein Beispielcode für das:

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;

Dann sollten Sie dies in Ihrem Code verwenden, wenn Sie die gestarteten Anwendungen herunterfahren möchten:

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;

Andere Tipps

Ich würde verwenden TJvCreateProcess Komponente von JVCL die Wraps über jedes Verfahren ähnliche Funktionalität von win32 in einer anmutigen Art und Weise. Diese Antwort kommt von Dont-touch-winapi-es sei denn-wirklich-required Abteilung: -)

Die einzige generische Art und Weise einen Prozess zu stoppen, ist TerminateProcess . Aber das ist so weit von anmutig wie Sie bekommen können. Um anmutig einen Prozess zu schließen, müssen Sie den Prozess sagen, dass Sie möchten, um es zu stoppen, und dann hoffen, dass es gehorcht. Es gibt keine Möglichkeit, dass im Allgemeinen zu tun, aber.

Für ein GUI-Programm, ist die übliche Art und Weise, es zu sagen, dass Sie es laufen stoppen wollen, ist das Hauptfenster zu schließen. Es gibt keine formale Idee der „Hauptfenster“, though. Ein Programm kann null oder mehr Fenster hat, und es gibt keinen Weg nach außen zu wissen, was man Ihnen angeblich zu schließen, um das Programm aufhören zu arbeiten zu machen.

Sie könnten verwenden EnumWindows , um durch alle Fenster und wählen Sie diejenigen, die zu Ihrem Prozess gehören. (Sie würden diejenigen sein, für die GetWindowThreadProcessId den gleichen Prozess gibt ID, dass Createprocess hat Ihnen.)

Schließen eines Fensters möglicherweise nicht genug sein. Das Programm könnte ein Dialogfeld (Aufforderung zur Bestätigung, oder fragt, Änderungen zu speichern, etc.) angezeigt werden soll. Sie müßten im Voraus wissen, wie das Dialogfeld schließen.

Nicht-GUI-Programme können ähnliche Probleme haben. Es könnte sein, genug, um einen Strg + C Tastendruck zu simulieren. Es könnte, dass der Tastendruck anders fangen und zu handhaben, aber. Es könnte ein Menüsystem, das Sie „Q“, um das Programm zu beenden.

eingeben erwartet

Kurz gesagt, können Sie nicht ordnungsgemäß ein Programm schließen, wenn Sie im Voraus wissen, wie das Programm geschlossen werden erwartet.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top