2003. december 21., vasárnap

Starting and stopping Windows services


Problem/Question/Abstract:

Starting and stopping Windows services

Answer:

When installing certain types of programs it maybe necessary to restart related services to avoid conflicts. Regardless of the reason why you need to control services, following functions can help you with starting and stopping services running on the local computer or on a remote machine.

uses WinSvc;

//
// start service
//
// return TRUE if successful
//
// sMachine:
//   machine name, ie: \\SERVER
//   empty = local machine
//
// sService
//   service name, ie: Alerter
//

function ServiceStart(
  sMachine,
  sService: 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: DWord;
begin
  ss.dwCurrentState := -1;

  // connect to the service
  // control manager
  schm := OpenSCManager(
    PChar(sMachine),
    nil,
    SC_MANAGER_CONNECT);

  // if successful...
  if (schm > 0) then
  begin
    // open a handle to
    // the specified service
    schs := OpenService(
      schm,
      PChar(sService),
      // 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 (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;

The procedure to stop a service is similar to starting a service, except for calling "ControlService()" Win32 function instead of "StartService()", checking for SERVICE_STOPPED rather than SERVICE_RUNNING and using appropriate control codes.

// stop service
//
// return TRUE if successful
//
// sMachine:
//   machine name, ie: \\SERVER
//   empty = local machine
//
// sService
//   service name, ie: Alerter
//

function ServiceStop(
  sMachine,
  sService: string): boolean;
var
  //
  // service control
  // manager handle
  schm,
    //
  // service handle
  schs: SC_Handle;
  //
  // service status
  ss: TServiceStatus;
  //
  // check point
  dwChkP: DWord;
begin
  // connect to the service
  // control manager
  schm := OpenSCManager(
    PChar(sMachine),
    nil,
    SC_MANAGER_CONNECT);

  // if successful...
  if (schm > 0) then
  begin
    // open a handle to
    // the specified service
    schs := OpenService(
      schm,
      PChar(sService),
      // 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;

Example usage:

if (ServiceStart('\\ComputerName', 'alerter')) then
begin
  // "alerter" service on \\ComputerName
  // was started
  // take appropriate action here
end;

// stop "alerter" service
// running on the local
// computer
if (ServiceStop('', 'alerter')) then
begin
end;

Nincsenek megjegyzések:

Megjegyzés küldése