Innosetup script to manage services

Posted on: Fri, 02/25/2011 - 14:06 By: ldsandon
Information Technology

An InnoSetup 5.x library to control services. It gives access to the Service Control Manager functions to query/start/stop/install/uninstall services, and implements some higher level functions (simpleXXXX) to perform standard tasks easily.

NB: this version won't work with the Unicode version of Inno Setup. Attached below there is a unicode version, I didn't test all functions yet. Use at your own risk.

<br />
//<br />
// Services functions for InnoSetup 5.x<br />
// Version 1.1<br />
//<br />
// The contents of this file are subject to the Mozilla Public License<br />
// Version 1.1 (the "License"); you may not use this file except in<br />
// compliance with the License. You may obtain a copy of the License at<br />
// <a href="http://www.mozilla.org/MPL/
//
//">http://www.mozilla.org/MPL/<br />
//<br />
//</a> Software distributed under the License is distributed on an "AS IS"<br />
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the<br />
// License for the specific language governing rights and limitations<br />
// under the License.<br />
//<br />
// The Original Code is services.iss.<br />
//<br />
// The Initial Developer of the Original Code is Luigi D. Sandon<br />
// Copyright © 2006-2008 Luigi D. Sandon. All Rights Reserved.<br />
//<br />
//<br />
// Note on passing PChars using RemObjects Pascal Script<br />
// '' pass a nil PChar<br />
// #0 pass an empty PChar<br />
//</p>
<p>type<br />
  _SERVICE_STATUS = record<br />
    dwServiceType: Longword;<br />
    dwCurrentState: Longword;<br />
    dwControlsAccepted: Longword;<br />
    dwWin32ExitCode: Longword;<br />
    dwServiceSpecificExitCode: Longword;<br />
    dwCheckPoint: Longword;<br />
    dwWaitHint: Longword;<br />
  end;</p>
<p>const<br />
  NO_ERROR = 0;<br />
  STANDARD_RIGHTS_REQUIRED = $F0000;</p>
<p>  //<br />
  // Service Control Manager object specific access types<br />
  //<br />
  SC_MANAGER_CONNECT = $0001;<br />
  SC_MANAGER_CREATE_SERVICE = $0002;<br />
  SC_MANAGER_ENUMERATE_SERVICE = $0004;<br />
  SC_MANAGER_LOCK = $0008;<br />
  SC_MANAGER_QUERY_LOCK_STATUS = $0010;<br />
  SC_MANAGER_MODIFY_BOOT_CONFIG = $0020;</p>
<p>  SC_MANAGER_ALL_ACCESS  =<br />
    (STANDARD_RIGHTS_REQUIRED +<br />
    SC_MANAGER_CONNECT +<br />
    SC_MANAGER_CREATE_SERVICE +<br />
    SC_MANAGER_ENUMERATE_SERVICE +<br />
    SC_MANAGER_LOCK +<br />
    SC_MANAGER_QUERY_LOCK_STATUS +<br />
    SC_MANAGER_MODIFY_BOOT_CONFIG);</p>
<p>  //<br />
  // No change constant<br />
  //<br />
  SERVICE_NO_CHANGE = $FFFFFFFF;</p>
<p>  //<br />
  // Service Types (Bit Mask)<br />
  //<br />
  SERVICE_KERNEL_DRIVER = $00000001;<br />
  SERVICE_FILE_SYSTEM_DRIVER = $00000002;<br />
  SERVICE_ADAPTER = $00000004;<br />
  SERVICE_RECOGNIZER_DRIVER = $00000008;</p>
<p>  SERVICE_DRIVER =<br />
    (SERVICE_KERNEL_DRIVER +<br />
     SERVICE_FILE_SYSTEM_DRIVER +<br />
     SERVICE_RECOGNIZER_DRIVER);</p>
<p>  SERVICE_WIN32_OWN_PROCESS = $00000010;<br />
  SERVICE_WIN32_SHARE_PROCESS = $00000020;<br />
  SERVICE_WIN32 =<br />
    (SERVICE_WIN32_OWN_PROCESS +<br />
    SERVICE_WIN32_SHARE_PROCESS);</p>
<p>  SERVICE_INTERACTIVE_PROCESS = $00000100;</p>
<p>  SERVICE_TYPE_ALL =<br />
    (SERVICE_WIN32 +<br />
    SERVICE_ADAPTER +<br />
    SERVICE_DRIVER +<br />
    SERVICE_INTERACTIVE_PROCESS);</p>
<p>  //<br />
  // Start Type<br />
  //<br />
  SERVICE_BOOT_START = $00000000;<br />
  SERVICE_SYSTEM_START = $00000001;<br />
  SERVICE_AUTO_START = $00000002;<br />
  SERVICE_DEMAND_START = $00000003;<br />
  SERVICE_DISABLED = $00000004;</p>
<p>  //<br />
  // Error control type<br />
  //<br />
  SERVICE_ERROR_IGNORE = $00000000;<br />
  SERVICE_ERROR_NORMAL = $00000001;<br />
  SERVICE_ERROR_SEVERE = $00000002;<br />
  SERVICE_ERROR_CRITICAL = $00000003;</p>
<p>  //<br />
  // Service object specific access type<br />
  //<br />
  SERVICE_QUERY_CONFIG = $0001;<br />
  SERVICE_CHANGE_CONFIG = $0002;<br />
  SERVICE_QUERY_STATUS = $0004;<br />
  SERVICE_ENUMERATE_DEPENDENTS = $0008;<br />
  SERVICE_START= $0010;<br />
  SERVICE_STOP= $0020;<br />
  SERVICE_PAUSE_CONTINUE = $0040;<br />
  SERVICE_INTERROGATE = $0080;<br />
  SERVICE_USER_DEFINED_CONTROL = $0100;</p>
<p>  SERVICE_ALL_ACCESS =<br />
    (STANDARD_RIGHTS_REQUIRED +<br />
    SERVICE_QUERY_CONFIG +<br />
    SERVICE_CHANGE_CONFIG +<br />
    SERVICE_QUERY_STATUS +<br />
    SERVICE_ENUMERATE_DEPENDENTS +<br />
    SERVICE_START +<br />
    SERVICE_STOP +<br />
    SERVICE_PAUSE_CONTINUE +<br />
    SERVICE_INTERROGATE +<br />
    SERVICE_USER_DEFINED_CONTROL);</p>
<p>  //<br />
  // Controls<br />
  //<br />
  SERVICE_CONTROL_STOP = $00000001;<br />
  SERVICE_CONTROL_PAUSE = $00000002;<br />
  SERVICE_CONTROL_CONTINUE = $00000003;<br />
  SERVICE_CONTROL_INTERROGATE = $00000004;</p>
<p>  //<br />
  // Status<br />
  //<br />
  SERVICE_CONTINUE_PENDING = $00000005;<br />
  SERVICE_PAUSE_PENDING = $00000006;<br />
  SERVICE_PAUSED = $00000007;<br />
  SERVICE_RUNNING = $00000004;<br />
  SERVICE_START_PENDING = $00000002;<br />
  SERVICE_STOP_PENDING = $00000003;<br />
  SERVICE_STOPPED = $00000001;</p>
<p>  //<br />
  //  Error codes<br />
  //<br />
  ERROR_DEPENDENT_SERVICES_RUNNING = 1051;<br />
  ERROR_INVALID_SERVICE_CONTROL = 1052;<br />
  ERROR_SERVICE_REQUEST_TIMEOUT = 1053;<br />
  ERROR_SERVICE_NO_THREAD = 1054;<br />
  ERROR_SERVICE_DATABASE_LOCKED = 1055;<br />
  ERROR_SERVICE_ALREADY_RUNNING = 1056;<br />
  ERROR_INVALID_SERVICE_ACCOUNT = 1057;<br />
  ERROR_SERVICE_DISABLED = 1058;<br />
  ERROR_CIRCULAR_DEPENDENCY = 1059;<br />
  ERROR_SERVICE_DOES_NOT_EXIST = 1060;<br />
  ERROR_SERVICE_CANNOT_ACCEPT_CTRL = 1061;<br />
  ERROR_SERVICE_NOT_ACTIVE = 1062;<br />
  ERROR_FAILED_SERVICE_CONTROLLER_CONNECT = 1063;<br />
  ERROR_EXCEPTION_IN_SERVICE = 1064;<br />
  ERROR_DATABASE_DOES_NOT_EXIST = 1065;<br />
  ERROR_SERVICE_SPECIFIC_ERROR = 1066;<br />
  ERROR_PROCESS_ABORTED = 1067;<br />
  ERROR_SERVICE_DEPENDENCY_FAIL = 1068;<br />
  ERROR_SERVICE_LOGON_FAILED = 1069;<br />
  ERROR_SERVICE_START_HANG = 1070;<br />
  ERROR_INVALID_SERVICE_LOCK = 1071;<br />
  ERROR_SERVICE_MARKED_FOR_DELETE = 1072;<br />
  ERROR_SERVICE_EXISTS = 1073;</p>
<p>function OpenSCManager(<br />
  lpMachineName: string;<br />
  lpDatabaseName: string;<br />
  dwDesiredAccess: Longword): Longword;<br />
  external '<a href="mailto:OpenSCManagerA@advapi32.dll">OpenSCManagerA@advapi32.dll</a> stdcall';</p>
<p>//<br />
// lpServiceName is the service name, not the service display name<br />
//</p>
<p>function OpenService(<br />
  hSCManager: Longword;<br />
  lpServiceName: string;<br />
  dwDesiredAccess: Longword): Longword;<br />
  external '<a href="mailto:OpenServiceA@advapi32.dll">OpenServiceA@advapi32.dll</a> stdcall';</p>
<p>function StartService(<br />
  hService: Longword;<br />
  dwNumServiceArgs: Longword;<br />
  lpServiceArgVectors: PChar): Longword;<br />
  external '<a href="mailto:StartServiceA@advapi32.dll">StartServiceA@advapi32.dll</a> stdcall';</p>
<p>function CloseServiceHandle(hSCObject: Longword): Longword;<br />
  external '<a href="mailto:CloseServiceHandle@advapi32.dll">CloseServiceHandle@advapi32.dll</a> stdcall';</p>
<p>function ControlService(<br />
  hService: Longword;<br />
  dwControl: Longword;<br />
  var lpServiceStatus: _SERVICE_STATUS): Longword;<br />
  external '<a href="mailto:ControlService@advapi32.dll">ControlService@advapi32.dll</a> stdcall';</p>
<p>function CreateService(hSCManager: Longword;<br />
  lpServiceName: string;<br />
  lpDisplayName: string;<br />
  dwDesiredAccess: Longword;<br />
  dwServiceType: Longword;<br />
  dwStartType: Longword;<br />
  dwErrorControl: Longword;<br />
  lpBinaryPathName: string;<br />
  lpLoadOrderGroup: string;<br />
  lpdwTagId: Longword;<br />
  lpDependencies: string;<br />
  lpServiceStartName: string;<br />
  lpPassword: string): Longword;<br />
  external '<a href="mailto:CreateServiceA@advapi32.dll">CreateServiceA@advapi32.dll</a> stdcall';</p>
<p>function DeleteService(hService: Longword): Longword;<br />
  external '<a href="mailto:DeleteService@advapi32.dll">DeleteService@advapi32.dll</a> stdcall';</p>
<p>function ChangeServiceConfig(<br />
  hService: Longword;<br />
  dwServiceType: Longword;<br />
  dwStartType: Longword;<br />
  dwErrorControl: Longword;<br />
  lpBinaryPathName: PChar;<br />
  lpLoadOrderGroup: PChar;<br />
  lpdwTagId: Longword;<br />
  lpDependencies: PChar;<br />
  lpServiceStartName: PChar;<br />
  lpPassword: PChar;<br />
  lpDisplayName: PChar): Longword;<br />
  external '<a href="mailto:ChangeServiceConfigA@advapi32.dll">ChangeServiceConfigA@advapi32.dll</a> stdcall';</p>
<p>function LockServiceDatabase(hSCManager: Longword): Longword;<br />
  external '<a href="mailto:LockServiceDatabase@advapi32.dll">LockServiceDatabase@advapi32.dll</a> stdcall';</p>
<p>function UnlockServiceDatabase(ScLock: Longword): Longword;<br />
  external '<a href="mailto:UnlockServiceDatabase@advapi32.dll">UnlockServiceDatabase@advapi32.dll</a> stdcall';</p>
<p>function SimpleCreateService(<br />
  AServiceName,<br />
  ADisplayName,<br />
  AFileName: string;<br />
  AStartType: Longword;<br />
  AUser, APassword: string;<br />
  Interactive: Boolean;<br />
  IgnoreExisting: Boolean): Boolean;<br />
var<br />
  SCMHandle: Longword;<br />
  ServiceHandle: Longword;<br />
  ServiceType: Longword;<br />
  Error: Integer;<br />
begin<br />
  Result := False;<br />
  ServiceType := SERVICE_WIN32_OWN_PROCESS;<br />
  try<br />
    SCMHandle := OpenSCManager('', '', SC_MANAGER_ALL_ACCESS);<br />
    if SCMHandle = 0 then<br />
      RaiseException('<a href="mailto:OpenSCManager@SimpleCreateService">OpenSCManager@SimpleCreateService</a>: ' + AServiceName + ' ' +<br />
        SysErrorMessage(DLLGetLastError));<br />
    try<br />
      if AUser = '' then<br />
      begin<br />
        if Interactive then<br />
          ServiceType := ServiceType + SERVICE_INTERACTIVE_PROCESS;<br />
        APassword := '';<br />
      end;<br />
      ServiceHandle := CreateService(SCMHandle, AServiceName, ADisplayName,<br />
        SERVICE_ALL_ACCESS, ServiceType, AStartType, SERVICE_ERROR_NORMAL,<br />
        AFileName, '', 0, '', AUser, APassword);<br />
      if ServiceHandle = 0 then<br />
      begin<br />
        Error := DLLGetLastError;<br />
        if IgnoreExisting and (Error = ERROR_SERVICE_EXISTS) then<br />
          Exit<br />
        else<br />
          RaiseException('<a href="mailto:CreateService@SimpleCreateService">CreateService@SimpleCreateService</a>: ' + AServiceName +<br />
            ' ' + SysErrorMessage(Error));<br />
      end;<br />
      Result := True;<br />
    finally<br />
      if ServiceHandle <> 0 then<br />
        CloseServiceHandle(ServiceHandle);<br />
    end;<br />
  finally<br />
    if SCMHandle <> 0 then<br />
      CloseServiceHandle(SCMHandle);<br />
  end;<br />
end;</p>
<p>function WaitForService(ServiceHandle: Longword; AStatus: Longword): Boolean;<br />
var<br />
  PendingStatus: Longword;<br />
  ServiceStatus: _SERVICE_STATUS;<br />
  Error: Integer;<br />
begin<br />
  Result := False;</p>
<p>  case AStatus of<br />
    SERVICE_RUNNING: PendingStatus := SERVICE_START_PENDING;<br />
    SERVICE_STOPPED: PendingStatus := SERVICE_STOP_PENDING;<br />
  end;</p>
<p>  repeat<br />
    if ControlService(ServiceHandle, SERVICE_CONTROL_INTERROGATE, ServiceStatus) = 0 then<br />
    begin<br />
      Error := DLLGetLastError;<br />
      RaiseException('<a href="mailto:ControlService@WaitForService">ControlService@WaitForService</a>: ' + SysErrorMessage(Error));<br />
    end;<br />
    if ServiceStatus.dwWin32ExitCode <> 0 then<br />
      Break;<br />
    Result := ServiceStatus.dwCurrentState = AStatus;<br />
    if not Result and (ServiceStatus.dwCurrentState = PendingStatus) then<br />
      Sleep(ServiceStatus.dwWaitHint)<br />
    else<br />
      Break;<br />
  until Result;<br />
end;</p>
<p>procedure SimpleStopService(AService: string; Wait, IgnoreStopped: Boolean);<br />
var<br />
  ServiceStatus: _SERVICE_STATUS;<br />
  SCMHandle: Longword;<br />
  ServiceHandle: Longword;<br />
  Error: Integer;<br />
begin<br />
  try<br />
    SCMHandle := OpenSCManager('', '', SC_MANAGER_ALL_ACCESS);<br />
    if SCMHandle = 0 then<br />
      RaiseException('<a href="mailto:OpenSCManager@SimpleStopService">OpenSCManager@SimpleStopService</a>: ' + AService + ' ' +<br />
        SysErrorMessage(DLLGetLastError));<br />
    try<br />
      ServiceHandle := OpenService(SCMHandle, AService, SERVICE_ALL_ACCESS);<br />
      if ServiceHandle = 0 then<br />
        RaiseException('<a href="mailto:OpenService@SimpleStopService">OpenService@SimpleStopService</a>: ' + AService + ' ' +<br />
          SysErrorMessage(DLLGetLastError));<br />
      try<br />
        if ControlService(ServiceHandle, SERVICE_CONTROL_STOP, ServiceStatus) = 0 then<br />
        begin<br />
          Error := DLLGetLastError;<br />
          if IgnoreStopped and (Error = ERROR_SERVICE_NOT_ACTIVE) then<br />
            Exit<br />
          else<br />
            RaiseException('<a href="mailto:ControlService@SimpleStopService">ControlService@SimpleStopService</a>: ' + AService + ' ' +<br />
              SysErrorMessage(Error));<br />
          if Wait then<br />
            WaitForService(ServiceHandle, SERVICE_STOPPED);<br />
        end;<br />
      finally<br />
        if ServiceHandle <> 0 then<br />
          CloseServiceHandle(ServiceHandle);<br />
      end;<br />
    finally<br />
      if SCMHandle <> 0 then<br />
        CloseServiceHandle(SCMHandle);<br />
    end;<br />
  except<br />
    ShowExceptionMessage;<br />
  end;<br />
end;</p>
<p>procedure SimpleStartService(AService: string; Wait, IgnoreStarted: Boolean);<br />
var<br />
  SCMHandle: Longword;<br />
  ServiceHandle: Longword;<br />
  Error: Integer;<br />
begin<br />
  try<br />
    SCMHandle := OpenSCManager('', '', SC_MANAGER_ALL_ACCESS);<br />
    if SCMHandle = 0 then<br />
      RaiseException('<a href="mailto:OpenSCManager@SimpleStartService">OpenSCManager@SimpleStartService</a>: ' + AService + ' ' +<br />
        SysErrorMessage(DLLGetLastError));<br />
    try<br />
      ServiceHandle := OpenService(SCMHandle, AService, SERVICE_ALL_ACCESS);<br />
      if ServiceHandle = 0 then<br />
        RaiseException('<a href="mailto:OpenService@SimpleStartService">OpenService@SimpleStartService</a>: ' + AService + ' ' +<br />
          SysErrorMessage(DLLGetLastError));<br />
      try<br />
        if StartService(ServiceHandle, 0, '') = 0 then<br />
        begin<br />
          Error := DLLGetLastError;<br />
          if IgnoreStarted and (Error = ERROR_SERVICE_ALREADY_RUNNING) then<br />
            Exit<br />
          else<br />
            RaiseException('<a href="mailto:StartService@SimpleStartService">StartService@SimpleStartService</a>: ' + AService + ' ' +<br />
              SysErrorMessage(Error));<br />
          if Wait then<br />
          begin<br />
            WaitForService(ServiceHandle, SERVICE_RUNNING);<br />
          end;<br />
        end;<br />
      finally<br />
        if ServiceHandle <> 0 then<br />
          CloseServiceHandle(ServiceHandle);<br />
      end;<br />
    finally<br />
      if SCMHandle <> 0 then<br />
        CloseServiceHandle(SCMHandle);<br />
    end;<br />
  except<br />
    ShowExceptionMessage;<br />
  end;<br />
end;</p>
<p>procedure SimpleDeleteService(AService: string);<br />
var<br />
  SCMHandle: Longword;<br />
  ServiceHandle: Longword;<br />
begin<br />
  try<br />
    SCMHandle := OpenSCManager('', '', SC_MANAGER_ALL_ACCESS);<br />
    if SCMHandle = 0 then<br />
      RaiseException('<a href="mailto:OpenSCManager@SimpleDeleteService">OpenSCManager@SimpleDeleteService</a>: ' + AService + ' ' +<br />
        SysErrorMessage(DLLGetLastError));<br />
    try<br />
      ServiceHandle := OpenService(SCMHandle, AService, SERVICE_ALL_ACCESS);<br />
      if ServiceHandle = 0 then<br />
        RaiseException('<a href="mailto:OpenService@SimpleDeleteService">OpenService@SimpleDeleteService</a>: ' + AService + ' ' +<br />
          SysErrorMessage(DLLGetLastError));<br />
      try<br />
        if DeleteService(ServiceHandle) = 0 then<br />
          RaiseException('<a href="mailto:StartService@SimpleDeleteService">StartService@SimpleDeleteService</a>: ' + AService + ' ' +<br />
            SysErrorMessage(DLLGetLastError));<br />
      finally<br />
        if ServiceHandle <> 0 then<br />
          CloseServiceHandle(ServiceHandle);<br />
      end;<br />
    finally<br />
      if SCMHandle <> 0 then<br />
        CloseServiceHandle(SCMHandle);<br />
    end;<br />
  except<br />
    ShowExceptionMessage;<br />
  end;<br />
end;</p>
<p>procedure SimpleSetServiceStartup(AService: string; AStartupType: Longword);<br />
var<br />
  SCMHandle: Longword;<br />
  ServiceHandle: Longword;<br />
begin<br />
  try<br />
    SCMHandle := OpenSCManager('', '', SC_MANAGER_ALL_ACCESS);<br />
    if SCMHandle = 0 then<br />
      RaiseException('<a href="mailto:SimpleSetServiceStartup@OpenSCManager">SimpleSetServiceStartup@OpenSCManager</a>: ' + AService + ' ' +<br />
        SysErrorMessage(DLLGetLastError));<br />
    try<br />
      ServiceHandle := OpenService(SCMHandle, AService, SERVICE_ALL_ACCESS);<br />
      if ServiceHandle = 0 then<br />
        RaiseException('<a href="mailto:SimpleSetServiceStartup@OpenService">SimpleSetServiceStartup@OpenService</a>: ' + AService + ' ' +<br />
          SysErrorMessage(DLLGetLastError));<br />
      try<br />
        if ChangeServiceConfig(ServiceHandle, SERVICE_NO_CHANGE, AStartupType, SERVICE_NO_CHANGE,<br />
          '', '', 0, '', '', '', '') = 0 then<br />
          RaiseException('<a href="mailto:SimpleSetServiceStartup@SetServiceStartup">SimpleSetServiceStartup@SetServiceStartup</a>: ' + AService + ' ' +<br />
            SysErrorMessage(DLLGetLastError));<br />
      finally<br />
        if ServiceHandle <> 0 then<br />
          CloseServiceHandle(ServiceHandle);<br />
      end;<br />
    finally<br />
      if SCMHandle <> 0 then<br />
        CloseServiceHandle(SCMHandle);<br />
    end;<br />
  except<br />
    ShowExceptionMessage;<br />
  end;<br />
end;</p>
<p>function ServiceExists(AService: string): Boolean;<br />
var<br />
  SCMHandle: Longword;<br />
  ServiceHandle: Longword;<br />
  Error: Integer;<br />
begin<br />
  try<br />
    SCMHandle := OpenSCManager('', '', SC_MANAGER_ALL_ACCESS);<br />
    if SCMHandle = 0 then<br />
      RaiseException('<a href="mailto:OpenSCManager@ServiceExists">OpenSCManager@ServiceExists</a>: ' + AService + ' ' +<br />
        SysErrorMessage(DLLGetLastError));<br />
    try<br />
      ServiceHandle := OpenService(SCMHandle, AService, SERVICE_ALL_ACCESS);<br />
      try<br />
        if ServiceHandle = 0 then<br />
        begin<br />
          Error := DLLGetLastError;<br />
          if Error = ERROR_SERVICE_DOES_NOT_EXIST then<br />
            Result := False<br />
          else<br />
            RaiseException('<a href="mailto:OpenService@ServiceExists">OpenService@ServiceExists</a>: ' + AService + ' ' +<br />
              SysErrorMessage(Error));<br />
        end<br />
        else<br />
          Result := True;<br />
      finally<br />
        if ServiceHandle <> 0 then<br />
          CloseServiceHandle(ServiceHandle);<br />
      end;<br />
    finally<br />
      if SCMHandle <> 0 then<br />
        CloseServiceHandle(SCMHandle);<br />
    end;<br />
  except<br />
    ShowExceptionMessage;<br />
  end;<br />
end;</p>
<p>function SimpleQueryService(AService: string): Longword;<br />
var<br />
  ServiceStatus: _SERVICE_STATUS;<br />
  SCMHandle: Longword;<br />
  ServiceHandle: Longword;<br />
  Error: Integer;<br />
begin<br />
  Result := 0;<br />
  try<br />
    SCMHandle := OpenSCManager('', '', SC_MANAGER_ALL_ACCESS);<br />
    if SCMHandle = 0 then<br />
      RaiseException('<a href="mailto:OpenSCManager@SimpleQueryService">OpenSCManager@SimpleQueryService</a>: ' + AService + ' ' +<br />
        SysErrorMessage(DLLGetLastError));<br />
    try<br />
      ServiceHandle := OpenService(SCMHandle, AService, SERVICE_ALL_ACCESS);<br />
      if ServiceHandle = 0 then<br />
        RaiseException('<a href="mailto:OpenService@SimpleQueryService">OpenService@SimpleQueryService</a>: ' + AService + ' ' +<br />
          SysErrorMessage(DLLGetLastError));<br />
      try<br />
        if ControlService(ServiceHandle, SERVICE_CONTROL_INTERROGATE, ServiceStatus) = 0 then<br />
        begin<br />
          Error := DLLGetLastError;<br />
          RaiseException('<a href="mailto:ControlService@SimpleQueryService">ControlService@SimpleQueryService</a>: ' + AService + ' ' +<br />
            SysErrorMessage(Error));<br />
        end;<br />
        Result := ServiceStatus.dwCurrentState;<br />
      finally<br />
        if ServiceHandle <> 0 then<br />
          CloseServiceHandle(ServiceHandle);<br />
      end;<br />
    finally<br />
      if SCMHandle <> 0 then<br />
        CloseServiceHandle(SCMHandle);<br />
    end;<br />
  except<br />
    ShowExceptionMessage;<br />
  end;<br />
end;<br />
[/delphi]<br />
</p>