Lagi bikin tools kecil untuk start dan stop Delphi, setelah googling nemu di sini. Tapi karena procedural, jadi gatel untuk mengubah ke class wised. Hal lain kalau mau menjalankan atau menghentikan service mesti menyebutkan WorkstationNamenya. Berarti kalau mau mendapatkan nama computer di mana program ini berjalan, mesti cari lagi. Hasil google mengarah ke sini. Ternyata kalau ada di domain, nama workstation saja masih tidak dikenali. Harus lengkap beserta domainnya. Lihat help di Delphi (F1), dapatlah GetComputerNameEx. Nah aku tambahkan juga method yang bisa mengenali workstation di mana programnya dijalankan. Aku sengaja tidak mengubah rutin yang di dapat dari Sadikhov forum di atas, hanya ditambahkan wrapper saja.
unit unitServiceControl; interface uses WinSvc, SysUtils, Windows; { Main Routine for Services : TARZAN from http://www.sadikhov.com/forum/index.php?showtopic=9039 Main Routine for ComputerName : Zarko Gajic from http://delphi.about.com/cs/adptips2002/a/bltip0102_3.htm OOP Wrapper and minor enhancement and variable type correction : Wisnu Widiarta (7 April 2011) } type TServiceControl = class public class function StartService(workstationName, serviceName: String) : boolean; class function StopService(workstationName, serviceName: String) : boolean; class function StartServiceInCurrentWorkstation(serviceName: String): Boolean; class function StopServiceInCurrentWorkstation(serviceName: String): Boolean; class function GetComputerNetName: String; end; implementation { TServiceControl } // // start service // // return TRUE if successful // // sMachine: // machine name, ie: \SERVER // empty = local machine // // sService // service name, ie: Alerter // class function TServiceControl.StartService(workstationName, serviceName: string): boolean; var // // service control // manager handle schm, // // service handle schs : SC_Handle; // // service status ss : TServiceStatus; // // temp char pointer psTemp : PChar; // // check point dwChkP : Word; begin ss.dwCurrentState := 0; // connect to the service // control manager schm := OpenSCManager( PChar(workstationName), Nil, SC_MANAGER_CONNECT); // if successful... if(schm > 0)then begin // open a handle to // the specified service schs := OpenService( schm, PChar(serviceName), // we want to // start the service and SERVICE_START or // query service status SERVICE_QUERY_STATUS); // if successful... if(schs > 0)then begin psTemp := Nil; if(WinSvc.StartService( schs, 0, psTemp))then begin // check status if(QueryServiceStatus( schs, ss))then begin while(SERVICE_RUNNING <> ss.dwCurrentState)do begin // // dwCheckPoint contains a // value that the service // increments periodically // to report its progress // during a lengthy // operation. // // save current value // dwChkP := ss.dwCheckPoint; // // wait a bit before // checking status again // // dwWaitHint is the // estimated amount of time // the calling program // should wait before calling // QueryServiceStatus() again // // idle events should be // handled here... // Sleep(ss.dwWaitHint); if(not QueryServiceStatus( schs, ss))then begin // couldn't check status // break from the loop break; end; if(ss.dwCheckPoint < dwChkP)then begin // QueryServiceStatus // didn't increment // dwCheckPoint as it // should have. // avoid an infinite // loop by breaking break; end; end; end; end; // close service handle CloseServiceHandle(schs); end; // close service control // manager handle CloseServiceHandle(schm); end; // return TRUE if // the service status is running Result := SERVICE_RUNNING = ss.dwCurrentState; end; // // stop service // // return TRUE if successful // // sMachine: // machine name, ie: \SERVER // empty = local machine // // sService // service name, ie: Alerter // class function TServiceControl.StartServiceInCurrentWorkstation( serviceName: String): Boolean; begin Result := StartService(GetComputerNetName, serviceName); end; class function TServiceControl.StopService(workstationName, serviceName: string): boolean; var // // service control // manager handle schm, // // service handle schs : SC_Handle; // // service status ss : TServiceStatus; // // check point dwChkP : Word; begin // connect to the service // control manager schm := OpenSCManager( PChar(workstationName), Nil, SC_MANAGER_CONNECT); // if successful... if(schm > 0)then begin // open a handle to // the specified service schs := OpenService( schm, PChar(serviceName), // we want to // stop the service and SERVICE_STOP or // query service status SERVICE_QUERY_STATUS); // if successful... if(schs > 0)then begin if(ControlService( schs, SERVICE_CONTROL_STOP, ss))then begin // check status if(QueryServiceStatus( schs, ss))then begin while(SERVICE_STOPPED <> ss.dwCurrentState)do begin // // dwCheckPoint contains a // value that the service // increments periodically // to report its progress // during a lengthy // operation. // // save current value // dwChkP := ss.dwCheckPoint; // // wait a bit before // checking status again // // dwWaitHint is the // estimated amount of time // the calling program // should wait before calling // QueryServiceStatus() again // // idle events should be // handled here... // Sleep(ss.dwWaitHint); if(not QueryServiceStatus( schs, ss))then begin // couldn't check status // break from the loop break; end; if(ss.dwCheckPoint < dwChkP)then begin // QueryServiceStatus // didn't increment // dwCheckPoint as it // should have. // avoid an infinite // loop by breaking break; end; end; end; end; // close service handle CloseServiceHandle(schs); end; // close service control // manager handle CloseServiceHandle(schm); end; // return TRUE if // the service status is stopped Result := SERVICE_STOPPED = ss.dwCurrentState; end; class function TServiceControl.StopServiceInCurrentWorkstation( serviceName: String): Boolean; begin Result := StopService(GetComputerNetName, serviceName); end; class function TServiceControl.GetComputerNetName: String; var buffer: PWideChar; size: Cardinal; begin size := 256; GetMem(buffer, size); if GetComputerNameEx(ComputerNameDnsFullyQualified, buffer, size) then Result := buffer else Result := ''; FreeMem(buffer, size); end; end.
Penggunaannya simple saja:
const SERVICE_NAME = 'BlackfishSQL'; {$R *.dfm} procedure TformMain.btnStartClick(Sender: TObject); begin Log('Trying to stop SERVICE ' + SERVICE_NAME + ' in ' + TServiceControl.GetComputerNetName + '...'); if TServiceControl.StopServiceInCurrentWorkstation(SERVICE_NAME) then Log('Service ' + SERVICE_NAME + ' has been stopped...') else Log('Service ' + SERVICE_NAME + ' cannot be stopped. Try to stopped it manually.'); //Untuk dikomputer xxx if TServiceControl.StopService('xxx', SERVICE_NAME) then Log('Service ' + SERVICE_NAME + ' has been stopped...') else Log('Service ' + SERVICE_NAME + ' cannot be stopped. Try to stopped it manually.'); end; procedure TformMain.Log(event: String); begin mmLog.Lines.Add(FormatDateTime('DD/MM/YY hh:mm:ss', Now) + ' >> ' + event); end;
PS: Kode ini kalau dijalankan di beberapa PC looping infinite. Kalau itu terjadi mungkin bisa mencoba cara lain dengan jalan memanggil aplikasi net.exe dari dos dengan perintah dari Delphi memanggil function ShellExecute yang bisa diperoleh dari unit ShellApi. Perintah untuk start adalah net.exe start <nama service>. Untuk menghentikan service, net.exe stop <nama service>.
Tinggalkan komentar