Delphi-PRAXiS
Seite 1 von 2  1 2      

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 "wird beendet" (https://www.delphipraxis.net/137822-dienst-wird-beendet.html)

FriFra 29. Jul 2009 01:07


Dienst "wird beendet"
 
Ich habe einen eigentlich recht simplen Dienst, welcher beim start über shellexecute ein anderes Programm aufruft. Wenn dieses andere Programm beendet wird, piped dieses eine Message zum Service, welcher sich daraufhin beenden soll. dazu verwende ich einen Timer, welcher eine Variable überwacht, die duch die Message verändert wird:
Delphi-Quellcode:
procedure TEasyServer.Timer1Timer(Sender: TObject);
begin
  if uPipesService.bShutDown then
  begin
    Timer1.Enabled := False;
    FServer.ShutDownServer; //TPipeServer
    FServer.Free;
    EasyServer.DoStop;

  end;
end;
Die Message kommt offensichtlich an, denn der Status des Service wechselt zu "wird beendet"... aber er beendet sich nicht. Es gibt nirgends irgendwelche Schleifen oder ähnliches... ich hab keine Erklärung, warum der Prozess weiter läuft.

Apollonius 29. Jul 2009 15:53

Re: Dienst "wird beendet"
 
Behandelst du das Ereignis OnStop?

FriFra 29. Jul 2009 20:42

Re: Dienst "wird beendet"
 
Ja, da pipe ich noch eine message zu einem anderen Programm (das sich übrigens daraufhin korrekt beendet) und dann sollte eigentlich schluß sein... ist es aber nicht
Delphi-Quellcode:
procedure TEasyServer.ServiceStop(Sender: TService; var Stopped: Boolean);
var
  PipeClient: TPipeClient;
begin
  PipeClient := TPipeClient.Create('', 'easyServerPipe');
  PipeClient.SendString('quit');
  PipeClient.Free;
  Stopped := True;
end;
Wenn ich den dienst über den Dienste-Manager beende piped er die genannten Messages auch an die anderen Programme, aber da wird er dann auch beendet. ich habe langsam den Verdacht das DoStop nicht die richtige Methode ist... Ich würde den dienst auch knallhart abschießen, wenn es denn eine Terminate methode gäbe...

FriFra 30. Jul 2009 21:55

Re: Dienst "wird beendet"
 
:roll: hat keiner eine Idee?

quendolineDD 30. Jul 2009 23:42

Re: Dienst "wird beendet"
 
Es gab doch noch OnShutdown welches beim Beenden aufgerufen wurde. Habe länger nichts mehr mit Services zu tun gehabt und könnte mich dann auch erinnern. Aber ich habe damals an zwei Stellen meine Funktion zum beenden aller Threads (war ein Multithread-Service) aufgerufen.

FriFra 31. Jul 2009 09:38

Re: Dienst "wird beendet"
 
Wenn sich der Service selbst beenden soll, wird bei mir OnShutdown NICHT aufgerufen... ich hab das gerad mal mit Messageboxen geprüft... wenn ich den Dienst über den Dienste-Manager beende, durchläuft der OnStop und Onshutdown und wird sauber beendet.

Es gibt definitiv keine nicht geschlossenen Objekte mehr, die das verursachen können... Ich steh auf dem Schlauch :gruebel:

P.S.: Ich habe auch keine echten Threads, sondern nur eigenständige Anwendungen, welche über Pipes mit dem Server (Consolen-Anwendung) reden, der wiederrum dem Dienst (dient nur als Starter) über Pipes mitteilt, wenn er beendet wird.

FriFra 31. Jul 2009 21:35

Re: Dienst "wird beendet"
 
Ich habs jetzt aufgegeben den Dienst dazu bewegen zu wollen, sich selber zu beenden... Jetzt sennde ich eben keine Message mehr, die den Dienst dazu bringt sich zu beenden, sondern rufe einfach folgenden Code auf:
Delphi-Quellcode:
            ShellExecute(0, 'open', 'net', 'stop EasyServer', '', 0);
Damit ist das Problem gelöst.

skateracer 12. Mär 2010 11:43

Re: Dienst "wird beendet"
 
Bei mir funktioniert nur diese Schreibweise:

ShellExecute(0, 'open', 'cmd', PCHAR('/k' + 'net stop "David Grabbing Server"'), '', 0);

Luckie 12. Mär 2010 11:48

Re: Dienst "wird beendet"
 
Das setzt aber voraus, dass das vom Service gestartete Programm als Administrator läuft.

Dezipaitor 12. Mär 2010 12:33

Re: Dienst "wird beendet"
 
Es gibt einige Probleme mit den Shellfunktionen, wenn man sie aus einem Dienst startet.

Man kann einen Dienst ganz einfach beenden, indem man die Executemethode verlässt.
In den JWSCL Beispielen gibt es einige Dienste, die Pipes verwenden (ja sogar mehrere) und auf deren Ende warten und trotzdem die Dienstmanagernachrichten beantworten. (z.B. unvollendete Projekt: XPElevation -> MainUnit.pas)

Delphi-Quellcode:
   try //except
      try
        fThreadsStoppedEvent  := CreateEvent(nil, true, false, nil);
        fServiceStopEvent  := CreateEvent(nil, true, false, nil);
        Sleep(1000);


        ZeroMemory(@OvLapped, sizeof(OvLapped));
        OvLapped.hEvent := CreateEvent(nil, false, false, nil);
...

          try
            Pipe := CreateServicePipe(Log);
            repeat
              ConnectNamedPipe(Pipe, @OvLapped);

              repeat
                if Assigned(ServiceThread) then
                  ServiceThread.ProcessRequests(False);


                if (TJwWindowsVersion.IsWindowsXP(true) or
                    TJwWindowsVersion.IsWindows2003(true)) and
                      (GetSystemMetrics(SM_SHUTTINGDOWN) <> 0) then
                    Stopped := true;

                SetLastError(0);
                WaitResult := JwMsgWaitForMultipleObjects([fServiceStopEvent, OvLapped.hEvent], false, INFINITE, QS_ALLINPUT);

                case WaitResult of
                  WAIT_OBJECT_0 + 1 : ResetEvent(OvLapped.hEvent);
                  WAIT_OBJECT_0 + 2 : PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE); //tag message as read
                else
                  OutputDebugString(PChar(IntToStr(GetLastError)));
                end;

              until WaitResult <> WAIT_OBJECT_0 + 2; //
             
              if WaitResult = WAIT_OBJECT_0 +1 then //OvLapped.hEvent
              begin
                ...
                {We use this pipe only a very short time so it is very unlikely
                that several clients are going to connect at the same time.
                }
                PipeName := THandleRequestThread.CreatePipeName(UniquePipeID);
               
                ReadFile(Pipe, @ProtocolVersion, sizeof(ProtocolVersion) ,nil, @OvLapped2);

                if JwWaitForMultipleObjects([fServiceStopEvent, OvLapped2.hEvent], false,
                      {$IFNDEF DEBUG}1000{$ELSE}INFINITE{$ENDIF}) = WAIT_OBJECT_0 +1 then
                begin
... //Pipeclient und extra Thread übergeben.
                end;
...
...
              Sleep(5000);
              DisconnectNamedPipe(Pipe);

            until Stopped;

          finally
//signal server shutdown
            Stopped := true;

            {Wait for all threads to be stopped or timeout
             Set by a method that is called by threads which are finished.
             It decreases a value down to 0 and then fires the event.
            }
            WaitForSingleObject(ThreadsStopEvent, 30 * 1000);
         
            fPasswords.Free;
          end;
Und manuelles Stopereignis:
Delphi-Quellcode:
procedure TXPService.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
  SetEvent(fServiceStopEvent);
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:22 Uhr.
Seite 1 von 2  1 2      

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