Delphi - Anmutig Schließen Erstellt Prozess in Service. (Unter Verwendung von TProcess / Create)
-
06-07-2019 - |
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?
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 erwartetKurz gesagt, können Sie nicht ordnungsgemäß ein Programm schließen, wenn Sie im Voraus wissen, wie das Programm geschlossen werden erwartet.