Wie funktioniert das mit den CustomControlCodes?
So hier.....
Vorweg, mit DoCustomControl kann man nur einseitig etwas an den Service schicken
In diesem Beispiel gehe ich über eine vordefinierte Trigger-Liste TServiceControlCode um ans Ziel zu gelangen.
Das gehört in den Service
Delphi-Quellcode:
//Protected TMyService Deklaration überschreiben
function DoCustomControl(CtrlCode: DWord): Boolean; override;
// hier definiere ich Namen als Nummer, passe Namen an Deine Wunschtrigger an
type
TServiceControlCode = (scRefreshProcesses, scUnused1, scUnused2, scUnused3, scUnused4, scUnused5, scUnused6, scUnused7);
function TNyService.DoCustomControl(CtrlCode: DWord): Boolean;
var
ProcessKey, Command, I: Integer;
begin
Result := True;
I := CtrlCode and 127;
ProcessKey := I shr 3;
Command := I and 7; // die 7 muss zu der Menge der Trigger passen, bei 0 beginnend!
if ProcessKey = 0 then
begin
case TServiceControlCode(Command) of
scRefreshProcesses: begin end; // was soll passieren wenn scRefreshProcesses getriggert wurde?
end;
end;
end;
Das gehört in Applikation
Delphi-Quellcode:
// hier definiere ich Namen als Nummer, passe Namen an Deine Wunschtrigger an
type
TServiceControlCode = (scRefreshProcesses, scUnused1, scUnused2, scUnused3, scUnused4, scUnused5, scUnused6, scUnused7);
function EncodeServiceControlCode(ProcessKey, ControlCode: Byte): DWord;
begin
Result := 128 + ((ProcessKey and 15) shl 3) + (ControlCode and 7); // die 7 muss zu der Menge der Trigger passen, bei 0 beginnend!
end;
procedure SendServiceControlCode(ServiceHND: SC_HANDLE; ControlCode: DWord);
var
ServiceStatus: TServiceStatus;
begin
if Win32Check(QueryServiceStatus(ServiceHND, ServiceStatus)) then
if (ServiceStatus.dwCurrentState and (SERVICE_STOPPED or SERVICE_STOP_PENDING)) = 0 then
Win32Check(ControlService(ServiceHND, ControlCode, ServiceStatus))
else RaiseLastOSError(GetLastError());
end;
function GetServiceHandle(const ComputerName, ServiceName: String): SC_HANDLE;
var
SCManagerHND, ServiceHND: SC_HANDLE;
begin
ServiceHND := := 0;
SCManagerHND := OpenSCManager(PAnsiChar(ComputerName), nil, SC_MANAGER_ALL_ACCESS);
if SCManagerHND <> 0 then
begin
ServiceHND := OpenService(SCManagerHND, PAnsiChar(ServiceName), SERVICE_QUERY_STATUS or SERVICE_USER_DEFINED_CONTROL);
end;
Result := ServiceHND;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
// ersetze 'DeinServiceName' mit Deinem Service Namen
// ersetze Ord(scRefreshProcesses) mit was auch immer du triggern möchtest
SendServiceControlCode(GetServiceHandle('','DeinServiceName'), EncodeServiceControlCode(0, Ord(scRefreshProcesses)));
// GetServiceHandle('','DeinServiceName') So = Lokal
// GetServiceHandle('RemotePC','RemoteServiceName') So = Remote
end;
Weitere Hilfe zu diesem Thema
Das Ermitteln des
Handle:
OpenSCManager und
OpenService
Das Senden:
QueryServiceStatus und
ControlService
Hilft Dir das weiter?
Ich(oder rein Kollege) hatte mal nen Versuch mit Memory Maped Files
...das war auch nicht gerade zuverlässig
...scheinbar ist es möglich das MMF irgendwie blockiert wird.
IPC ist da eine schlechte Wahl, Service und Applikation laufen ja getrennt, Service sollte ja überall verfügbar sein aber Applikation ist auf Konto/Rechte gebunden. Es ist zwar Möglich aber mit mehr Aufwand als nötig.