AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi CreateProcess und gestarteten Prozess automatisch beenden wenn Anwendung beendet wird
Thema durchsuchen
Ansicht
Themen-Optionen

CreateProcess und gestarteten Prozess automatisch beenden wenn Anwendung beendet wird

Ein Thema von Bernhard Geyer · begonnen am 12. Mär 2014 · letzter Beitrag vom 19. Sep 2014
Antwort Antwort
Seite 2 von 2     12   
Der schöne Günther
Online

Registriert seit: 6. Mär 2013
6.110 Beiträge
 
Delphi 10 Seattle Enterprise
 
#11

AW: CreateProcess und gestarteten Prozess automatisch beenden wenn Anwendung beendet

  Alt 19. Sep 2014, 18:01
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.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:39 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz