Einzelnen Beitrag anzeigen

Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.685 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Windows Service Kommunikation

  Alt 20. Mai 2018, 00:09
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.
Gruß vom KodeZwerg

Geändert von KodeZwerg (20. Mai 2018 um 10:42 Uhr) Grund: Links und Hilfe addiert
  Mit Zitat antworten Zitat