用下面的控件可以解决:
unit CNTServiceCtrl;
interface
uses
WinSvc, Windows, classes, Dialogs;
type
TCNTServiceCtrlStatusEvent = procedure (Sender: TObject; const Status: String) of object;
TCNTServiceCtrlErrorEvent = procedure (Sender: TObject; const ErrCode: DWORD; const Description: String) of object;
TCNTServiceCtrl = class(TComponent)
private
schm, schs: SC_Handle;
ss: TServiceStatus;
FActive: Boolean;
FOnError: TCNTServiceCtrlErrorEvent;
FOnStatus: TCNTServiceCtrlStatusEvent;
FService: String;
FMachine: String;
function ServiceStopped : boolean;
function ServiceRunning : boolean;
function GetServiceActive : boolean;
procedure SetActive(const Value: Boolean);
procedure SetMachine(const Value: String);
procedure SetService(const Value: String);
procedure ShowStatus(const Value: String);
procedure ShowError(const aErrCode: DWORD; const Value: String);
function GetErrorMessage (code : Integer) : string;
procedure SetServiceActive(const Value: Boolean);
public
constructor Create(Owner: TComponent); override;
destructor Destroy; override;
function Start: boolean;
function Stop : boolean;
function Restart: boolean;
function ServiceGetStatus : Longint;
published
property Machine: String read FMachine write SetMachine;
property Service: String read FService write SetService;
property Active: Boolean read FActive write SetActive default False;
property ServiceActive: Boolean read GetServiceActive write SetServiceActive default False;
property OnStatus: TCNTServiceCtrlStatusEvent read FOnStatus write FOnStatus;
property OnError: TCNTServiceCtrlErrorEvent read FOnError write FOnError;
end;
procedure Register;
implementation
function TCNTServiceCtrl.Start: boolean;
var
psTemp : PChar;
ErrCode: DWORD;
MaxCount, Count: Integer;
begin
If FActive then begin
ShowStatus('Attempt to start service ' + FService + ' on ' + FMachine);
if(StartService(schs, 0, psTemp))then begin
ServiceGetStatus;
if ss.dwWaitHint > 1000 then
MaxCount := round(ss.dwWaitHint / 100.0)
else
MaxCount := 30;
Count := 0;
while (not ServiceRunning) and (Count < MaxCount) do begin
Sleep(1000);
Inc(Count);
if ServiceGetStatus = -1 then break;
end;
end
else begin
ErrCode := GetLastError;
ShowError(ErrCode, 'StartService() ' + GetErrorMessage(ErrCode));
end;
end
else begin
ShowError(0, 'Start() Service Control Object not activated');
end;
Result := SERVICE_RUNNING = ss.dwCurrentState;
if not Result then ShowError(0, 'Service Start Failed');
end;
function TCNTServiceCtrl.Stop : boolean;
var
maxCount, Count : Integer;
begin
if FActive then begin
ShowStatus('Attempt to stop service ' + FService + ' on ' + FMachine);
if(ControlService(schs, SERVICE_CONTROL_STOP, ss))then begin
if ss.dwWaitHint > 1000 then
MaxCount := round(ss.dwWaitHint / 100.0)
else
MaxCount := 30;
Count := 0;
while (not ServiceStopped) and (Count < MaxCount) do begin
Sleep(1000);
Inc(Count);
if ServiceGetStatus = -1 then break;
end;
end;
end
else begin
ShowError(0, 'Stop() Service Control Object not activated');
end;
Result := SERVICE_STOPPED = ss.dwCurrentState;
if not Result then ShowError(0, 'Service Stop Failed');
end;
function TCNTServiceCtrl.ServiceGetStatus : longint;
var
dwStat : Longint;
ErrCode: DWORD;
begin
dwStat := -1;
if FActive then begin
if(QueryServiceStatus(schs, ss))then begin
dwStat := ss.dwCurrentState;
end
else begin
ErrCode := GetLastError;
ShowError(ErrCode, 'QueryServiceStatus() ' + GetErrorMessage(ErrCode));
end;
end
else begin
ShowError(0, 'ServiceGetStatus() Service Control Object not activated');
end;
case dwStat of
SERVICE_STOPPED: ShowStatus('Service Stopped');
SERVICE_START_PENDING: ShowStatus('Service Start Pending');
SERVICE_STOP_PENDING: ShowStatus('Service Stop Pending');
SERVICE_RUNNING: ShowStatus('Service Running');
SERVICE_CONTINUE_PENDING: ShowStatus('Service Coutinue Pending');
SERVICE_PAUSE_PENDING: ShowStatus('Service Pause Pending');
SERVICE_PAUSED: ShowStatus('Service Paused');
end;
Result := dwStat;
end;
function TCNTServiceCtrl.Restart: boolean;
begin
Result := False;
if ServiceRunning then begin
if Stop then begin
if Start then Result := True;
end;
end
else begin
ShowError(0, 'Service Not Started');
end;
if not Result then ShowError(0, 'Restart Service Fail');
end;
function TCNTServiceCtrl.ServiceRunning : boolean;
begin
Result := (SERVICE_RUNNING = ServiceGetStatus);
end;
function TCNTServiceCtrl.ServiceStopped : boolean;
begin
Result := (SERVICE_STOPPED = ServiceGetStatus);
end;
procedure TCNTServiceCtrl.SetActive(const Value: Boolean);
var
ErrCode: DWORD;
begin
if (Value and not FActive) then begin
schm := OpenSCManager(PChar(FMachine), Nil, SC_MANAGER_CONNECT);
if(schm > 0)then begin
ShowStatus('Connected to Service Control Manager');
schs := OpenService(schm, PChar(FService), SERVICE_ALL_ACCESS);
if(schs > 0)then begin
ShowStatus('Service ' + FService + ' in control');
FActive := True;
end
else begin
ErrCode := GetLastError;
ShowError(ErrCode, 'OpenService() ' + GetErrorMessage(ErrCode));
end;
end
else begin
ErrCode := GetLastError;
ShowError(ErrCode, 'OpenSCManager() ' + GetErrorMessage(ErrCode));
end;
end
else if (not Value and FActive) then begin
CloseServiceHandle(schs);
CloseServiceHandle(schm);
FActive := False;
end;
end;
constructor TCNTServiceCtrl.Create(Owner: TComponent);
begin
inherited Create(Owner);
FMachine := '//';
FService := '';
end;
destructor TCNTServiceCtrl.Destroy;
begin
SetActive(False);
inherited Destroy;
end;
procedure TCNTServiceCtrl.SetMachine(const Value: String);
begin
if Value <> FMachine then SetActive(False);
FMachine := Value;
ShowStatus('Machine = ' + FMachine);
end;
procedure TCNTServiceCtrl.SetService(const Value: String);
begin
if Value <> FService then SetActive(False);
FService := Value;
ShowStatus('Service = ' + FService);
end;
procedure TCNTServiceCtrl.ShowStatus(const Value: String);
begin
if Assigned(FOnStatus) then FOnStatus(Self, Value);
end;
procedure TCNTServiceCtrl.ShowError(const aErrCode: DWORD; const Value: String);
begin
if Assigned(FOnError) then FOnError(Self, aErrCode, 'ERROR: ' + Value)
else MessageDlg(Value, mtError, [mbOK], 0);
end;
procedure TCNTServiceCtrl.SetServiceActive(const Value: Boolean);
begin
if Value then Start
else Stop;
end;
function TCNTServiceCtrl.GetServiceActive: boolean;
begin
if FActive then
Result := ServiceRunning
else
Result := False;
end;
function TCNTServiceCtrl.GetErrorMessage(code : Integer) : string;
var
hErrLib : THandle;
msg : PChar;
flags : Integer;
begin
hErrLib := LoadLibraryEx ('netmsg.dll', 0, LOAD_LIBRARY_AS_DATAFILE);
try
flags := FORMAT_MESSAGE_ALLOCATE_BUFFER or
FORMAT_MESSAGE_IGNORE_INSERTS or
FORMAT_MESSAGE_FROM_SYSTEM;
if hErrLib <> 0 then
flags := flags or FORMAT_MESSAGE_FROM_HMODULE;
if FormatMessage (flags, pointer (hErrLib), code,
(SUBLANG_DEFAULT shl 10) or LANG_NEUTRAL,
@msg, 0, Nil) <> 0 then
try
result := msg;
finally
LocalFree (Integer (msg));
end
finally
if hErrLib <> 0 then
FreeLibrary (hErrLib)
end
end;
procedure Register;
begin
RegisterComponents('System', [TCNTServiceCtrl]);
end;
end.