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:
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.
procedure TEasyServer.Timer1Timer(Sender: TObject);
begin if uPipesService.bShutDown then begin Timer1.Enabled := False; FServer.ShutDownServer; //TPipeServer FServer.Free; EasyServer.DoStop; end; end; |
Re: Dienst "wird beendet"
Behandelst du das Ereignis OnStop?
|
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:
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...
procedure TEasyServer.ServiceStop(Sender: TService; var Stopped: Boolean);
var PipeClient: TPipeClient; begin PipeClient := TPipeClient.Create('', 'easyServerPipe'); PipeClient.SendString('quit'); PipeClient.Free; Stopped := True; end; |
Re: Dienst "wird beendet"
:roll: hat keiner eine Idee?
|
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.
|
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. |
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:
Damit ist das Problem gelöst.
ShellExecute(0, 'open', 'net', 'stop EasyServer', '', 0);
|
Re: Dienst "wird beendet"
Bei mir funktioniert nur diese Schreibweise:
ShellExecute(0, 'open', 'cmd', PCHAR('/k' + 'net stop "David Grabbing Server"'), '', 0); |
Re: Dienst "wird beendet"
Das setzt aber voraus, dass das vom Service gestartete Programm als Administrator läuft.
|
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:
Und manuelles Stopereignis:
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;
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. |
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