Start and Stop Service using Delphi


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>.

Iklan

Posted on April 7, 2011, in Pemrograman and tagged . Bookmark the permalink. 17 Komentar.

  1. Kayaknya dulu, jaman masih jadi coder di windows, aku juga pernah bikin tool beginian deh. Buat start/stop development tools dari tray bar, mulai delphi-nya, db server, web server, package builder, dsb. Tapi ntah ada dimana tuh program dan source code-nya ya? 😀

  2. Btw… WordPress.com udah bisa balik ke classic/normal view. Protesmu didengerin, bro. 🙂

  3. Wogghh bahasa yang tak dimengerti awam …
    Rumit juga ya dibalik tombol-tombol komputer ini ..

    • Sebenarnya semuanya diterjemahkan ke dalam biner.. 1 dan 0. Lalu diterjemahkan sebagai ada arus dan tidak ada arus… Sunatullah Bang. 🙂

  4. saua masih bergelut dengan PHP dan MySQL 🙂

  5. kok saya tidak bisa getComputerNameEx dan ComputerNameDnsFullyQualified?

    tidak dikenali keduanya.

    mohon bantuannya yah

    thx

  6. apa win 7 tidak support ya?

    thx

Tinggalkan Balasan

Isikan data di bawah atau klik salah satu ikon untuk log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s

%d blogger menyukai ini: