{*******************************************************************************
Description: provides functions to control and check status of
service applications
Last change: 26. July 2009
based on
http://www.delphipraxis.net/topic105934_dienstservice+starten+stoppen+oder+status+abfragen.html
*******************************************************************************}
unit ServiceFunctions;
interface
{$IFNDEF UNICODE}
type
UnicodeString = WideString;
{$ENDIF}
function IsServiceInstalled(
const ServiceName: UnicodeString;
const MachineName: UnicodeString = '
'): Boolean;
function IsServiceRunning(
const ServiceName: UnicodeString;
const MachineName: UnicodeString = '
'): Boolean;
// the following functions need admin rights (will trigger UAC under Vista+)
function ServiceStart(
const ServiceName: UnicodeString;
const MachineName: UnicodeString = '
'): Boolean;
function ServiceStop(
const ServiceName: UnicodeString;
const MachineName: UnicodeString = '
'): Boolean;
function ServiceRestart(
const ServiceName: UnicodeString;
const MachineName: UnicodeString = '
'): Boolean;
implementation
uses
Windows, WinSvc
{$IFNDEF UNICODE}, SysUtils
{$ENDIF};
//------------------------------------------------------------------------------
// internal helper functions
//------------------------------------------------------------------------------
function WrappedOpenServiceManager(
const MachineName: UnicodeString): SC_HANDLE;
begin
{$IFNDEF UNICODE}
if (Win32Platform = VER_PLATFORM_WIN32_NT)
then
Result := OpenSCManagerW(PWideChar(MachineName),
nil, SC_MANAGER_CONNECT)
else
{$ENDIF}
// Note: the following uses the Wide-Version when using an Unicode capable
// Delphi version (D2009+) but the Ansi-Version with lower Delphi versions.
// Do not remove the string() type for this wanted and correct behaviour.
Result := OpenSCManager(PChar(
string(MachineName)),
nil, SC_MANAGER_CONNECT);
end;
function WrappedOpenService(
const ManagerHandle: SC_HANDLE;
const ServiceName: UnicodeString;
const DesiredAccess: Cardinal): SC_HANDLE;
begin
{$IFNDEF UNICODE}
if (Win32Platform = VER_PLATFORM_WIN32_NT)
then
Result := OpenServiceW(ManagerHandle, PWideChar(ServiceName), DesiredAccess)
else
{$ENDIF}
// Note: the following uses the Wide-Version when using an Unicode capable
// Delphi version (D2009+) but the Ansi-Version with lower Delphi versions.
// Do not remove the string() type for this wanted and correct behaviour.
Result := OpenService(ManagerHandle, PChar(
string(ServiceName)), DesiredAccess);
end;
procedure WrappedQueryServiceStatus(
const SvcHandle: SC_HANDLE;
var ServiceStatus: TServiceStatus;
const StatusWaitingFor: Cardinal);
var
dwCheckPoint: DWORD;
begin
if QueryServiceStatus(SvcHandle, ServiceStatus)
then
begin
while (ServiceStatus.dwCurrentState <> StatusWaitingFor)
do
begin
dwCheckPoint := ServiceStatus.dwCheckPoint;
Sleep(ServiceStatus.dwWaitHint);
if (
not QueryServiceStatus(SvcHandle, ServiceStatus))
then
// couldn't check status
Break;
if (ServiceStatus.dwCheckPoint < dwCheckPoint)
then
Break;
end;
end;
end;
function GetServiceStatus(
const ServiceName, MachineName: UnicodeString): Cardinal;
{
Parameters:
ServiceName specifies the name of the service to open
MachineName specifies the name of the target computer
Return Values:
0 Error opening service
1 SERVICE_STOPPED
2 SERVICE_START_PENDING
3 SERVICE_STOP_PENDING
4 SERVICE_RUNNING
5 SERVICE_CONTINUE_PENDING
6 SERVICE_PAUSE_PENDING
7 SERVICE_PAUSED
}
var
SCManHandle,
SvcHandle: SC_Handle;
ServiceStatus: TServiceStatus;
dwStat: Cardinal;
begin
dwStat := 0;
SCManHandle := WrappedOpenServiceManager(MachineName);
if SCManHandle > 0
then
begin
try
SvcHandle := WrappedOpenService(SCManHandle, ServiceName,
SERVICE_QUERY_STATUS);
if SvcHandle > 0
then
begin
try
if QueryServiceStatus(SvcHandle, ServiceStatus)
then
dwStat := ServiceStatus.dwCurrentState;
finally
CloseServiceHandle(SvcHandle);
end;
end;
finally
CloseServiceHandle(SCManHandle);
end;
end;
Result := dwStat;
end;
//------------------------------------------------------------------------------
// public functions
//------------------------------------------------------------------------------
function IsServiceInstalled(
const ServiceName: UnicodeString;
const MachineName: UnicodeString = '
'): Boolean;
begin
Result := GetServiceStatus(ServiceName, MachineName) <> 0;
end;
function IsServiceRunning(
const ServiceName: UnicodeString;
const MachineName: UnicodeString = '
'): Boolean;
begin
Result := GetServiceStatus(ServiceName, MachineName) = SERVICE_RUNNING;
end;
function ServiceStart(
const ServiceName: UnicodeString;
const MachineName: UnicodeString = '
'): Boolean;
var
SCManHandle,
SvcHandle: SC_Handle;
ServiceStatus: TServiceStatus;
ServiceArgVectors: PChar;
begin
SCManHandle := WrappedOpenServiceManager(MachineName);
if SCManHandle > 0
then
begin
try
SvcHandle := WrappedOpenService(SCManHandle, ServiceName,
SERVICE_START
or SERVICE_QUERY_STATUS
or SC_MANAGER_ALL_ACCESS);
if SvcHandle > 0
then
begin
try
if StartService(SvcHandle, 0, ServiceArgVectors)
then // succeeded
WrappedQueryServiceStatus(SvcHandle, ServiceStatus, SERVICE_RUNNING);
finally
CloseServiceHandle(SvcHandle);
end;
end;
finally
CloseServiceHandle(SCManHandle);
end;
end;
Result := (ServiceStatus.dwCurrentState = SERVICE_RUNNING);
end;
function ServiceStop(
const ServiceName: UnicodeString;
const MachineName: UnicodeString = '
'): Boolean;
var
SCManHandle,
SvcHandle: SC_Handle;
ServiceStatus: TServiceStatus;
begin
SCManHandle := WrappedOpenServiceManager(MachineName);
if SCManHandle > 0
then
begin
try
SvcHandle := WrappedOpenService(SCManHandle, ServiceName,
SERVICE_STOP
or SERVICE_QUERY_STATUS);
if SvcHandle > 0
then
begin
try
if ControlService(SvcHandle, SERVICE_CONTROL_STOP, ServiceStatus)
then
WrappedQueryServiceStatus(SvcHandle, ServiceStatus, SERVICE_STOPPED);
finally
CloseServiceHandle(SvcHandle);
end;
end;
finally
CloseServiceHandle(SCManHandle);
end;
end;
Result := (ServiceStatus.dwCurrentState = SERVICE_STOPPED);
end;
function ServiceRestart(
const ServiceName: UnicodeString;
const MachineName: UnicodeString = '
'): Boolean;
begin
Result := ServiceStop(ServiceName, MachineName)
and
ServiceStart(ServiceName, MachineName);
end;
end.