Delphi - Pornire NT service cu parametri

Delphi - Pornire NT service cu parametri

Postby v0id » 07 Mar 2010, 18:10

StartService este una dintre functiile API din Windows cu care am avut o mare distractie recent, cand incercam sa pornesc un serviciu (NT Service) cu parametri (MS SQL Server, daca sunteti curiosi :) ).

Atentie: nu este vorba despre lansarea executabilului cu parametri din linie de comanda, ci despre parametrii care sa vor transmite functiei ServiceMain (sau obiectului de tip TService, daca e vorba despre un service scris in Delphi).

Atunci cand dorim sa trimitem un singur parametru, acest lucru se poate realiza simplu, apeland API-ul StartService in modul urmator: StartService('COMPUTER', 'SERVICE', PChar('PARAMETRU'));
Daca ne uitam insa pe MSDN la documentatia functiei StartService, vom vedea ca daca dorim sa pornim serviciul cu mai mult de un parametru, un simplu type-cast in PChar al unui sir de caractere ce contine toti parametrii nu va merge.

A rezultat astfel functia ServiceStartWithParam, care realizeaza ceea ce dorim si pe care o aveti mai jos.

Parametri ServiceStartWithParam:
aMachine - numele computerului pe care ruleaza serviciul
aService - numele serviciului (Atentie: Service Name, NU Display Name!)
aParams - un vector cu elemente de tip string ce va contine parametrii cu care va fi pornit serviciul

Rezultat ServiceStartWithParam:
True - serviciul a fost pornit
False - serviciul NU a fost pornit


  1.  
  2. ...
  3. uses WinSvc;
  4. ...
  5.  
  6. function ServiceStartWithParam(aMachine, aService: string; aParams: array of string): boolean;
  7. var
  8.   lhSCM: SC_Handle;
  9.   lhSvc: SC_Handle;
  10.   lStatus: TServiceStatus;
  11.   lCheckPoint: longint;
  12.  
  13.   lParamsArr: array of integer;
  14.   iCounter: integer;
  15. begin
  16.   lStatus.dwCurrentState := 0;
  17.  
  18.   // Conectare la SCM (Service Control Manager)
  19.   lhSCM := OpenSCManager(PChar(aMachine), nil, SC_MANAGER_CONNECT);
  20.  
  21.   if(lhSCM > 0)then
  22.     begin
  23.       // Incercam sa obtinem un handle catre serviciu. Vrem sa-l interogam si sa-l pornim (SERVICE_START or SERVICE_QUERY_STATUS).
  24.       lhSvc := OpenService(lhSCM, PChar(aService), SERVICE_START or SERVICE_QUERY_STATUS);
  25.  
  26.       if (lhSvc > 0) then
  27.         begin
  28.           // Adaugam parametrii intr-un array local
  29.           SetLength(lParamsArr, Length(aParams) + 1);
  30.           if (Length(aParams) <> 0) then
  31.             for iCounter := 0 to Length(aParams) - 1 do
  32.               lParamsArr[iCounter] := Integer(PChar(aParams[iCounter]));
  33.  
  34.           // Incercam sa pornim serviciul
  35.           if (StartService(lhSvc, Length(aParams), PChar(lParamsArr[0]))) then
  36.             begin
  37.               // Verificare status
  38.               if (QueryServiceStatus(lhSvc, lStatus)) then
  39.                 begin
  40.                   while (SERVICE_RUNNING <> lStatus.dwCurrentState) do
  41.                     begin
  42.                       // lCheckPoint contine o valoare pe care serviciul
  43.                       // o incrementeaza periodic pentru a raporta progresul.
  44.                       lCheckPoint := lStatus.dwCheckPoint;
  45.  
  46.                       // Asteptam inainte de a verifica statusul din nou
  47.                       Sleep(lStatus.dwWaitHint);
  48.  
  49.                       // Nu s-a putut verifica statusul, iesire din bucla
  50.                       if (not QueryServiceStatus(lhSvc, lStatus)) then
  51.                         Break;
  52.  
  53.                       // QueryServiceStatus nu a incrementat dwCheckPoint, iesire din bucla
  54.                       if lStatus.dwCheckPoint < lCheckPoint then
  55.                         Break;
  56.                     end;
  57.                 end;
  58.             end;
  59.  
  60.           // Inchidere handle serviciu
  61.           CloseServiceHandle(lhSvc);
  62.         end;
  63.       // Inchidere handle SCM
  64.       CloseServiceHandle(lhSCM);
  65.     end;
  66.  
  67.   // Intoarcem TRUE daca statusul serviciului este RUNNING
  68.   Result := SERVICE_RUNNING = lStatus.dwCurrentState;
  69. end;
  70.  



Un exemplu de apel al functiei:
  1.  
  2. procedure TForm1.Button1Click(Sender: TObject);
  3. var
  4.   lArr: array of string;
  5. begin
  6.   SetLength(lArr, 2);
  7.   lArr[0] := 'Param_01';
  8.   lArr[1] := 'Param_02';
  9.   ServiceStartWithParam('COMPUTER_NAME', 'SERVICE_NAME', lArr);
  10. end;
  11.  



Credits also to DarkByte ;)
2p / 1 votes
A good coder is never on holiday - he may be working on a different machine, that's about as far as it gets.
User avatar
v0id
Word
 
Joined: 05 Jan 2010
Location: 127.0.0.1
Status: 39.5

Return to Snippets

Who is online

Users browsing this forum: No registered users and 0 guests