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

17 tanggapan untuk “Start and Stop Service using Delphi”

  1. Bee Avatar

    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? 😀

    Suka

    1. wisnuwidiarta Avatar
      wisnuwidiarta

      Kalau di MacBook konsepnya kayak di linux ya? Macam kill -9 bla bla bla gitu, apa ada cara lain?

      Suka

      1. Bee Avatar

        Mac OSX itu Unix plus. Jadi, pake cara Unix bisa, pake cara Mac (kyk Windows API gitu) bisa, pake messaging (tool-nya Automator, sejenis VBA gitu) juga bisa. Tergantung kebutuhan dan preferensi aja.

        Suka

      2. wisnuwidiarta Avatar
        wisnuwidiarta

        Awesome dong ya?

        Suka

      3. Bee Avatar

        Biasa aja kali bro. Sama aja sama OS yg lain. 🙂

        Suka

      4. wisnuwidiarta Avatar
        wisnuwidiarta

        Maklum.. belum pernah mainan mac OS hehehe..

        Suka

  2. Bee Avatar

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

    Suka

    1. wisnuwidiarta Avatar
      wisnuwidiarta

      Bwakakaka… aku dah coba barusan. Jauuuuuuuuuuuuuh…. standard lots faster brooo!

      Suka

      1. Bee Avatar

        Iya nih, coding JS-nya masih gak optimized. Aku nyoba Sencha Touch yg lebih kompleks performanya masih lebih baik.

        Suka

      2. wisnuwidiarta Avatar
        wisnuwidiarta

        Sencha touch itu apaan? Theme?

        Suka

  3. Iksa Avatar

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

    Suka

    1. wisnuwidiarta Avatar
      wisnuwidiarta

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

      Suka

  4. rifki Avatar

    saua masih bergelut dengan PHP dan MySQL 🙂

    Suka

    1. wisnuwidiarta Avatar
      wisnuwidiarta

      Oh itu juga mengasyikkan kok….

      Suka

  5. Harryanto Avatar
    Harryanto

    kok saya tidak bisa getComputerNameEx dan ComputerNameDnsFullyQualified?

    tidak dikenali keduanya.

    mohon bantuannya yah

    thx

    Suka

  6. Harryanto Avatar
    Harryanto

    apa win 7 tidak support ya?

    thx

    Suka

    1. wisnuwidiarta Avatar
      wisnuwidiarta

      Aku cobanya pake XP. Di sini gak ada Vista atau Win 7. Bisa jadi udah beda APInya 😀

      Suka

Tinggalkan komentar

Situs ini menggunakan Akismet untuk mengurangi spam. Pelajari bagaimana data komentar Anda diproses.

I’m Wisnu Widiarta

Welcome to My Untold Contemplation blog, my cozy corner of the internet dedicated to all of my activities in social activities, outdoor sightseeing, watching movies, playing board game, and photography. If you share my interests, please connect or share your thoughts in my posting.

Let’s connect