unit service; // Some useful wrapper functions for NT Services. // Geoffrey Swift (c) 2006 interface uses Windows; function GetServiceStatus(const ServiceName: String): DWORD; function StartService(const ServiceName: String; const Wait: Boolean): DWORD; function StopService(const ServiceName: String; const Wait: Boolean): DWORD; implementation uses WinSvc, SysUtils; function GetServiceStatus(const ServiceName: String): DWORD; var SCManagerHandle, ServiceHandle: SC_HANDLE; ServiceStatus: TServiceStatus; begin SCManagerHandle := OpenSCManager(nil, nil, SC_MANAGER_CONNECT); ServiceHandle := OpenService(SCManagerHandle, PChar(ServiceName), SERVICE_QUERY_STATUS); if (ServiceHandle <> 0) and QueryServiceStatus(ServiceHandle, ServiceStatus) then Result := ServiceStatus.dwCurrentState else Result := SERVICE_STOPPED; CloseServiceHandle(ServiceHandle); CloseServiceHandle(SCManagerHandle); end; function StartService(const ServiceName: String; const Wait: Boolean): DWORD; var SCManagerHandle, ServiceHandle: SC_HANDLE; ServiceStatus: TServiceStatus; begin SCManagerHandle := OpenSCManager(nil, nil, SC_MANAGER_CONNECT); if SCManagerHandle = 0 then begin Result := GetLastError; Exit end; ServiceHandle := OpenService(SCManagerHandle, PChar(ServiceName), SERVICE_START or SERVICE_QUERY_STATUS); if ServiceHandle = 0 then begin Result := GetLastError; CloseServiceHandle(SCManagerHandle); Exit end; if not WinSvc.StartService(ServiceHandle, 0, CmdLine) then Result := GetLastError else if not Wait then Result := NO_ERROR else begin Result := NO_ERROR; { so far } repeat if not QueryServiceStatus(ServiceHandle, ServiceStatus) then Result := GetLastError else if (SERVICE_START_PENDING = ServiceStatus.dwCurrentState) then Sleep(ServiceStatus.dwWaitHint) until (NO_ERROR <> Result) or (SERVICE_START_PENDING <> ServiceStatus.dwCurrentState); if NO_ERROR <> Result then { Report error from QueryServiceStatus } else if ServiceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR then Result := ServiceStatus.dwServiceSpecificExitCode else Result := ServiceStatus.dwWin32ExitCode end; CloseServiceHandle(ServiceHandle); CloseServiceHandle(SCManagerHandle) end; function StopService(const ServiceName: String; const Wait: Boolean): DWORD; var SCManagerHandle, ServiceHandle: SC_HANDLE; ServiceStatus: TServiceStatus; begin SCManagerHandle := OpenSCManager(nil, nil, SC_MANAGER_CONNECT); if SCManagerHandle = 0 then begin Result := GetLastError; Exit end; ServiceHandle := OpenService(SCManagerHandle, PChar(ServiceName), SERVICE_STOP or SERVICE_QUERY_STATUS); if ServiceHandle = 0 then begin Result := GetLastError; CloseServiceHandle(SCManagerHandle); Exit end; if not ControlService(ServiceHandle, SERVICE_CONTROL_STOP, ServiceStatus) then Result := GetLastError else if not Wait then Result := NO_ERROR { so far } else begin Result := NO_ERROR; { so far } repeat if not QueryServiceStatus(ServiceHandle, ServiceStatus) then Result := GetLastError else if (SERVICE_STOP_PENDING = ServiceStatus.dwCurrentState) then Sleep(ServiceStatus.dwWaitHint) until (NO_ERROR <> Result) or (SERVICE_STOP_PENDING <> ServiceStatus.dwCurrentState); if NO_ERROR <> Result then { Report error from QueryServiceStatus } else if ServiceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR then Result := ServiceStatus.dwServiceSpecificExitCode else Result := ServiceStatus.dwWin32ExitCode end; CloseServiceHandle(ServiceHandle); CloseServiceHandle(SCManagerHandle) end; end.