In meiner Software UpdateRepair war es nötig bestimmte Windows-Dienste zu steuern. Das heißt Dienst starten, beenden und konfigurieren. Zu diesem Zweck habe ich mir eine Klasse geschrieben.
Download Klasse – Unit – Download Demo App – Download Demo Code
Die Anwendung ist denkbar einfach:
// Via statische Methoden TCsWindowsService.Start('Dienst name'); TCsWindowsService.Stop('Dienst name'); TCsWindowsService.Restart('Dienst name'); oder // Via Klassen-Instanz var WinService : TCsWindowsService; begin WinService := TCsWindowsService.Create('Dienst Name'); try WinService.Start; WinService.Stop; WinService.Restart; finally FreeAndNil(WinService); end; end;
Die Unit „CapSystems.Framework.Windows.Service.pas“:
unit CapSystems.Framework.Windows.Service; interface uses SysUtils, Classes, Windows, WinSvc; type TCsWindowsService = class; { -------------------------------------------------------------------------- } { Enumeratoren ------------------------------------------------------------- } { -------------------------------------------------------------------------- } TCsWindowsServiceStartMode = ( wssmDisabled, wssmAuto, wssmAutoDelay, wssmManual ); { -------------------------------------------------------------------------- } { TCsWindowsService -------------------------------------------------------- } { -------------------------------------------------------------------------- } TCsWindowsService = class(TPersistent) const SERVICES_REGISTRY_ROOT = HKEY_LOCAL_MACHINE; SERVICES_REGISTRY_PATH = '\SYSTEM\CurrentControlSet\services\'; SERVICES_REGISTRY_STARTMODE_AUTO = 2; SERVICES_REGISTRY_STARTMODE_AUTODELAY = 2; SERVICES_REGISTRY_STARTMODE_MANUEL = 3; SERVICES_REGISTRY_STARTMODE_DISABLED = 4; private FName: String; FDescription: String; FStartMode: TCsWindowsServiceStartMode; FImagePath: String; FDisplayName: String; protected class function StartModeToDWORD(AStartMode: TCsWindowsServiceStartMode): DWORD; public constructor Create(AServiceName: String; ALoadProperties: Boolean = False); class procedure OpenServices; virtual; class procedure LoadServiceProperties(AName: string; var ADisplayName: string; var ADescription: string; var AImagePath: string; var AStartMode: TCsWindowsServiceStartMode); overload; procedure LoadServiceProperties; overload; class function Start(AName: String): Boolean; overload; function Start: Boolean; overload; class function Stop(AName: String): Boolean; overload; function Stop: Boolean; overload; class function Restart(AName: String): Boolean; overload; function Restart: Boolean; overload; class function IsRunning(AName: String): Boolean; overload; function IsRunning: Boolean; overload; class function SetStartMode(AName: String; AStartMode: TCsWindowsServiceStartMode): Boolean; overload; function SetStartMode( AStartMode: TCsWindowsServiceStartMode): Boolean; overload; class function GetStartMode(AName: String): TCsWindowsServiceStartMode; overload; published property Name: String read FName; property StartMode: TCsWindowsServiceStartMode read FStartMode; property Description: String read FDescription; property ImagePath: String read FImagePath; property DisplayName: String read FDisplayName; end; implementation uses Registry, CapSystems.Framework.Windows.Process, CapSystems.Framework.FileSystem; { ---------------------------------------------------------------------------- } { TCsService------------------------------------------------------------------ } { ---------------------------------------------------------------------------- } constructor TCsWindowsService.Create(AServiceName: string; ALoadProperties: Boolean = False); begin inherited Create; FName := AServiceName; if ALoadProperties then Self.LoadServiceProperties; end; class procedure TCsWindowsService.OpenServices; begin //TCsProcess.Start('msc.exe', 'open', 'services.msc'); TCsProcess.Start(TCsPath.GetSystemRootDirectory + 'services.msc'); end; class procedure TCsWindowsService.LoadServiceProperties(AName: string; var ADisplayName: string; var ADescription: string; var AImagePath: string; var AStartMode: TCsWindowsServiceStartMode); begin // end; procedure TCsWindowsService.LoadServiceProperties; begin Self.LoadServiceProperties( FName, FDisplayName, FDescription, FImagePath, FStartMode ); end; class function TCsWindowsService.StartModeToDWORD( AStartMode: TCsWindowsServiceStartMode): DWORD; begin Result := Self.SERVICES_REGISTRY_STARTMODE_DISABLED; case AStartMode of wssmAuto: Result := Self.SERVICES_REGISTRY_STARTMODE_AUTO; wssmAutoDelay: Result := Self.SERVICES_REGISTRY_STARTMODE_AUTODELAY; wssmManual: Result := Self.SERVICES_REGISTRY_STARTMODE_MANUEL; end; end; class function TCsWindowsService.Start(AName: string): Boolean; var SCManager, SCService: THandle; ServiceStatus: TServiceStatus; p: PChar; begin Result := False; SCManager := OpenSCManager(nil, nil, SC_MANAGER_CONNECT); if SCManager = 0 then Exit; try SCService := OpenService(SCManager, PChar(AName), SERVICE_START or SERVICE_STOP or SERVICE_QUERY_STATUS); if SCService = 0 then Exit; try ZeroMemory(@ServiceStatus, SizeOf(ServiceStatus)); p := nil; if StartService(SCService, 0, p) then begin // warten bis der Service gestartet ist repeat if not QueryServiceStatus(SCService, ServiceStatus) then Break; until ServiceStatus.dwCurrentState <> SERVICE_START_PENDING; end else Exit; Result := True; finally CloseServiceHandle(SCService); end; finally CloseServiceHandle(SCManager); end; end; function TCsWindowsService.Start: Boolean; begin Result := Self.Start(FName); end; class function TCsWindowsService.Stop(AName: string): Boolean; var SCManager, SCService: THandle; ServiceStatus: TServiceStatus; p: PChar; begin Result := False; SCManager := OpenSCManager(nil, nil, SC_MANAGER_CONNECT); if SCManager = 0 then Exit; try SCService := OpenService(SCManager, PChar(AName), SERVICE_START or SERVICE_STOP or SERVICE_QUERY_STATUS); if SCService = 0 then Exit; try ZeroMemory(@ServiceStatus, SizeOf(ServiceStatus)); // Service beenden if not ControlService(SCService, SERVICE_CONTROL_STOP, ServiceStatus) then begin if GetLastError <> ERROR_SERVICE_NOT_ACTIVE then Exit; end else begin // warten bis der Service beendet ist repeat if not QueryServiceStatus(SCService, ServiceStatus) then Break; until ServiceStatus.dwCurrentState <> SERVICE_STOP_PENDING; end; Result := True; finally CloseServiceHandle(SCService); end; finally CloseServiceHandle(SCManager); end; end; function TCsWindowsService.Stop: Boolean; begin Result := Self.Stop(FName); end; class function TCsWindowsService.Restart(AName: string): Boolean; var SCManager, SCService: THandle; ServiceStatus: TServiceStatus; p: PChar; begin Result := False; SCManager := OpenSCManager(nil, nil, SC_MANAGER_CONNECT); if SCManager = 0 then Exit; try SCService := OpenService(SCManager, PChar(AName), SERVICE_START or SERVICE_STOP or SERVICE_QUERY_STATUS); if SCService = 0 then Exit; try ZeroMemory(@ServiceStatus, SizeOf(ServiceStatus)); // Service beenden if not ControlService(SCService, SERVICE_CONTROL_STOP, ServiceStatus) then begin if GetLastError <> ERROR_SERVICE_NOT_ACTIVE then Exit; end else begin // warten bis der Service beendet ist repeat if not QueryServiceStatus(SCService, ServiceStatus) then Break; until ServiceStatus.dwCurrentState <> SERVICE_STOP_PENDING; end; // Service starten p := nil; if StartService(SCService, 0, p) then begin // warten bis der Service gestartet ist repeat if not QueryServiceStatus(SCService, ServiceStatus) then Break; until ServiceStatus.dwCurrentState <> SERVICE_START_PENDING; end else Exit; Result := True; finally CloseServiceHandle(SCService); end; finally CloseServiceHandle(SCManager); end; end; function TCsWindowsService.Restart: Boolean; begin Result := Self.Restart(FName); end; class function TCsWindowsService.IsRunning(AName: string): Boolean; var SCManager, SCService: THandle; ServiceStatus: TServiceStatus; p: PChar; begin Result := False; SCManager := OpenSCManager(nil, nil, SC_MANAGER_CONNECT); if SCManager = 0 then Exit; try SCService := OpenService(SCManager, PChar(AName), SERVICE_START or SERVICE_STOP or SERVICE_QUERY_STATUS); if SCService = 0 then Exit; try ZeroMemory(@ServiceStatus, SizeOf(ServiceStatus)); QueryServiceStatus(SCService, ServiceStatus); Result := ServiceStatus.dwCurrentState = SERVICE_RUNNING; finally CloseServiceHandle(SCService); end; finally CloseServiceHandle(SCManager); end; end; function TCsWindowsService.IsRunning: Boolean; begin Result := Self.IsRunning(FName); end; class function TCsWindowsService.SetStartMode(AName: string; AStartMode: TCsWindowsServiceStartMode): Boolean; var Reg: TRegistry; StartModeWord: DWORD; begin Result := False; Reg := TRegistry.Create; try reg.RootKey := HKEY_LOCAL_MACHINE; if Reg.OpenKey(Self.SERVICES_REGISTRY_PATH, False) then begin if Reg.OpenKey(AName, False) then begin StartModeWord := 4; case AStartMode of wssmDisabled: StartModeWord := 4; wssmAuto: StartModeWord := 2; wssmAutoDelay: StartModeWord := 2; wssmManual: StartModeWord := 3; end; Reg.WriteInteger('Start', StartModeWord); if AStartMode = wssmAutoDelay then Reg.WriteInteger('DelayedAutoStart', 1) else Reg.WriteInteger('DelayedAutoStart', 0); Result := True; end; end; finally FreeAndNil(Reg); end; end; function TCsWindowsService.SetStartMode( AStartMode: TCsWindowsServiceStartMode): Boolean; begin Result := Self.SetStartMode(FName, AStartMode); end; class function TCsWindowsService.GetStartMode(AName: string): TCsWindowsServiceStartMode; var TempStartMode: TCsWindowsServiceStartMode; TempDescription: String; TempImagePath: String; TempDisplayName: String; begin Self.LoadServiceProperties( AName, TempDisplayName, TempDescription, TempImagePath, TempStartMode ); Result := TempStartMode; end; end.
Wichtig: Nur mit Admin-Rechten kann man auf die Dienste zu greifen. Hat man nicht Berechtigung geben die Funktionen False zurück. Du musst also deiner Anwendung ein Manifest hinzufügen.