Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Dienst, der auf das Herunterfahren eines Computers reagiert? (https://www.delphipraxis.net/111205-dienst-der-auf-das-herunterfahren-eines-computers-reagiert.html)

Piro 31. Mär 2008 15:20


Dienst, der auf das Herunterfahren eines Computers reagiert?
 
Hallo,

ist es möglich einen Dienst zu programmieren, der auf das Herunterfahren oder Ausloggen des Benutzer reagiert?

Ich habe es mal mit der unten aufgeführten Funktion in einem Dienst probiert aber ohne Erfolg.
Delphi-Quellcode:
...
type
  TMyUpTimeService = class(TService)
    procedure ServiceAfterInstall(Sender: TService);
    procedure ServiceBeforeUninstall(Sender: TService);
    procedure ServiceExecute(Sender: TService);
    procedure ServiceStart(Sender: TService; var Started: Boolean);
    procedure ServiceStop(Sender: TService; var Stopped: Boolean);
    procedure ServiceCreate(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
    function GetServiceController: TServiceController; override;
    procedure WMQueryEndSession(var Msg: TWMQueryEndSession); message WM_QUERYENDSESSION;
  end;
...
procedure TMyUpTimeService..WMQueryEndSession(var Msg: TWMQueryEndSession);
begin
 // Auf Windows Ereignis reagieren
 case Msg.Unused of
   Integer(ENDSESSION_LOGOFF) :
     begin
       // Code beim Logoff Ereignis
     end;
 else
   begin
       // Code beim Restart / Herunterfahren Ereignis
   end;
 end;

 // Windows kann herunter, neugestartet werden oder Benutzer kann sich ausloggen
 Msg.Result := 1;
end;
...
In meiner laufenden Anwendung funktioniert es wunderbar aber nicht wenn ich das in einen Dienst einbaue.

Wie müßte ich es umsetzen oder welche Technik müßte ich verwenden?

Vielen Dank. Sven

toms 31. Mär 2008 20:14

Re: Dienst, der auf das Herunterfahren eines Computers reagi
 
Hallo Sven,

Hier mal zwei Stichwörter, welche bei der Lösung weiterhelfen sollten:

Bei Google suchenSERVICE_CONTROL_SHUTDOWN Bei Google suchenCTRL_LOGOFF_EVENT

SirThornberry 31. Mär 2008 20:20

Re: Dienst, der auf das Herunterfahren eines Computers reagi
 
Dein Service ist kein Fenster und kann dementsprechend keine Nachrichten empfangen. Wenn dann musst du innerhalb deines Service ein Fenster erstellen und dieser kann dann die Nachricht verarbeiten wenn du mit Messages arbeiten willst.

wido 31. Mär 2008 20:50

Re: Dienst, der auf das Herunterfahren eines Computers reagi
 
1. Fenster zu erzeugen als Dienst ist ein absolutes NO GO. Man nutze diesbezüglich Google: Bei Google suchenShatter Attacks.
2. Selbst wenn er ein Fenster erstellen würde, würde er keine Nachricht bekommen.

Wie toms bereits erwähnt hat, ist die Verwendung des SERVICE_CONTROL_SHUTDOWN Events der richtige Weg. Wenn Du Deinen Service mit Hilfe des Service Projekts in Delphi entwickelt hast, kannst Du auf das Event einfach reagieren indem Du den OnShutdown Event Handler des TService Objekts benutzt. Du solltest übrigens nichts allzu komplexes im Shutdown Handler machen. Du hast 20 Sekunden Zeit, ansonsten dreht Dir der SCM einfach den Saft ab und schießt deinen Prozess ab.

Piro 31. Mär 2008 21:05

Re: Dienst, der auf das Herunterfahren eines Computers reagi
 
Wenn ich das OnShutdown Event benutze, wie kann ich dann zwischen Herunterfahren / Neustarten und Logoff unterscheiden?

Vielen Dank schon mal für die zahlreichen Informationen.

Schönen Abend noch.

Klaus01 31. Mär 2008 21:08

Re: Dienst, der auf das Herunterfahren eines Computers reagi
 
Guten Abend,

vielleicht hilft Dir dieser Eintrag aus dem msdn2 weiter.

Grüße
Klaus

wido 31. Mär 2008 21:10

Re: Dienst, der auf das Herunterfahren eines Computers reagi
 
OnShutdown wird ausschließlich beim Herunterfahren bzw. Neustarten ausgelöst. Für den User Logoff wirst Du SetConsoleCtrlHandler benutzen müssen um auf das CTRL_LOGOFF_EVENT Event reagieren zu können.

Ich war mal so frei und habs implementiert:

Delphi-Quellcode:
function CtrlHandlerFunction(dwCtrlType : DWORD) : BOOL; stdcall;
begin
  // Generell geben wir FALSE zurück, da wir nicht alle Events bearbeiten. Sollten
  // wir aber auf ein Event reagieren, so müssen wir TRUE zurück geben.
  result := false;
  case dwCtrlType of
    CTRL_LOGOFF_EVENT :
      begin
        // Mach was immer Du machen möchtest sobald der User ausloggt :)
        result := true;
      end;
    CTRL_SHUTDOWN_EVENT :
      begin
        // Wenn Du OnShutdown nutzt, ist das nicht notwendig, prinzipiell ließe
        // sich im Event Handler aber auch auf ein Herunterfahren reagieren.
        result := true;
      end;
  end;
end;

procedure TService1.ServiceExecute(Sender: TService);
begin
  SetConsoleCtrlHandler(@CtrlHandlerFunction, true);
end;
Wenn Du statt des Console Control Handlers lieber das OnShutdown Event verwenden möchtest von TService, lösch den Part hier einfach:

Delphi-Quellcode:
    CTRL_SHUTDOWN_EVENT :
      begin
        // Wenn Du OnShutdown nutzt, ist das nicht notwendig, prinzipiell ließe
        // sich im Event Handler aber auch auf ein Herunterfahren reagieren.
        result := true;
      end;
Der Code ist untested, weil ich derzeit nicht reloggen kann. Allerdings denke ich nicht, daß ich nen Fehler drin hab. Garantieren tu ich allerdings wie immer für nichts. Wer sich an meinem Coding Stil stört hat - ebenfalls wie immer - selbst schuld :P.


Alle Zeitangaben in WEZ +1. Es ist jetzt 14: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-2025 by Thomas Breitkreuz