Registriert seit: 14. Apr 2003
Ort: Stuttgart
1.701 Beiträge
Delphi 7 Professional
|
Re: Dienst "wird beendet"
12. Mär 2010, 13:33
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;
|
|
Zitat
|