![]() |
AW: CreateProcess und gestarteten Prozess automatisch beenden wenn Anwendung beendet
Falls es nochmal jemanden interessiert:
Ich habe das ganze mal in einen etwas komfortableren Wrapper gepackt. Die Benutzung sieht dann so aus:
Delphi-Quellcode:
begin
jobObj := TWinJob.Create('meinJob'); jobObj.KillContainingProcessesOnExit := True; // [Prozess mit CREATE_BREAKAWAY_FROM_JOB-Flag erstellen] jobObj.moveProcessTo(dasProzessHandle); ReadLn; jobObj.Free(); // Damit wird der Prozess wieder geschlossen end. Die passende Unit:
Delphi-Quellcode:
unit WindowsJob platform;
interface uses Winapi.Windows, WinAPI_Job_Header; type /// <summary> /// Repräsentiert einen Windows-Job- Siehe /// <see href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms684161(v=vs.85).aspx"> /// MSDN: Job Objects /// </see>. /// </summary> TWinJob = class public type TProcessHandle = Winapi.Windows.THandle; TJobHandle = Winapi.Windows.THandle; private /// <seealso cref="KillContainingProcessesOnExit" /> FKillContainingProcessesOnExit: Boolean; protected var /// <seealso cref="JobHandle" /> FJobHandle: TJobHandle; /// <remarks> /// Wird kein Name verwendet entspricht der Wert des Feldes /// <c>EmptyStr</c> /// </remarks> jobName: String; /// <summary> /// Enthält die /// <see href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms684156(v=vs.85).aspx"> /// JOBOBJECT_EXTENDED_LIMIT_INFORMATION /// </see>-Informationen des Jobs. Wird von /// <see cref="queryJobInformation" /> abgefragt. /// </summary> /// <seealso cref="KillContainingProcessesOnExit" /> extInfo: TJobObjectExtendedLimitInformation; protected /// <summary> /// Prüft, ob das in <see cref="JobHandle" /> abgelegte /// Handle auf eine fehlgeschlagene Job-Erstellung hindeutet. /// In diesem Fall wird eine <c>EOSError</c>-Exception /// geworfen /// </summary> /// <exception cref="EOSError" /> procedure checkJobHandle(); /// <summary> /// Aktualisiert die <c>ExtendedLimitInformation</c> dieses /// Jobs und legt diese im Feld /// <see cref="extInfo" /> ab. /// </summary> procedure queryJobInformation(); virtual; procedure setKillContainingProcessesOnExit(const Value: Boolean); public constructor Create(); overload; /// <exception cref="EOSError"> /// Wenn bereits ein event, semaphore, mutex, waitable timer oder /// file-mapping mit dem gleichen Namen existiert /// </exception> constructor Create(const jobName: String); overload; destructor Destroy(); override; /// <returns> /// Gibt an ob der Prozess erfolgreich in diesen Job /// verschoben werden konnte /// </returns> /// <remarks> /// Der mit <c>CreateProcess</c> erstellte Prozess muss mit dem /// <see cref="WinAPI_Job_Header.CREATE_BREAKAWAY_FROM_JOB" />-Flag /// in seinem <c>dwCreationFlags</c>-Parameter erstellt werden. /// Ansonsten schlägt die Methode fehl und gibt <c>False</c> zurück /// </remarks> function moveProcessTo(const processHandle: TProcessHandle): Boolean; public // properties /// <summary> /// Gibt an ob die im Job enthaltenen Prozesse <b>beim Schließen /// des letzten Handles auf den Job</b> vom Betriebssystem /// terminiert werden sollen /// </summary> property KillContainingProcessesOnExit: Boolean read FKillContainingProcessesOnExit write setKillContainingProcessesOnExit; property JobHandle: TJobHandle read FJobHandle; end; implementation uses System.SysUtils; { TWinJob } constructor TWinJob.Create(); begin inherited Create(); FJobHandle := CreateJobObject(nil, nil); jobName := EmptyStr; checkJobHandle(); end; procedure TWinJob.checkJobHandle(); var lastError: DWORD; begin if (jobHandle = 0) then begin lastError := GetLastError(); case lastError of ERROR_INVALID_HANDLE: raise {$REGION 'EOSError'} EOSError.Create( 'An event, semaphore, mutex, waitable timer, or file-mapping ' +'with the same name of "'+jobName+'" already ' +'exists. Cannot create Job.' ); {$ENDREGION 'EOSError'} else SetLastError(lastError); RaiseLastOSError(); end; end; end; constructor TWinJob.Create(const jobName: String); begin inherited Create(); self.jobName := jobName; FJobHandle := CreateJobObject(nil, PChar(jobName)); checkJobHandle(); end; destructor TWinJob.Destroy(); begin CloseHandle(jobHandle); inherited; end; function TWinJob.moveProcessTo(const processHandle: TProcessHandle): Boolean; begin Result := AssignProcessToJobObject(jobHandle, processHandle); end; procedure TWinJob.queryJobInformation(); begin Win32Check( QueryInformationJobObject( jobHandle, TJobObjectInfoClass.ExtendedLimitInformation, Addr(extInfo), SizeOf(extInfo), nil ) ); end; procedure TWinJob.setKillContainingProcessesOnExit(const Value: Boolean); const queryFirst: Boolean = True; var basicInfo: TJobObjectBasicLimitInformation; begin FKillContainingProcessesOnExit := Value; if queryFirst then queryJobInformation(); basicInfo := extInfo.BasicLimitInformation; if KillContainingProcessesOnExit then basicInfo.LimitFlags := basicInfo.LimitFlags or JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE else basicInfo.LimitFlags := basicInfo.LimitFlags and (not JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE); extInfo.BasicLimitInformation := basicInfo; Win32Check( SetInformationJobObject( jobHandle, TJobObjectInfoClass.ExtendedLimitInformation, Addr(extInfo), SizeOf(extInfo) ) ); end; end. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:07 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz