123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- { ***************************************************************************
- Copyright (c) 2016-2018 Kike Pérez
- Unit : Quick.Service
- Description : Service functions
- Author : Kike Pérez
- Version : 1.1
- Created : 14/07/2017
- Modified : 30/08/2018
- This file is part of QuickLib: https://github.com/exilon/QuickLib
- ***************************************************************************
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- *************************************************************************** }
- unit Quick.Service;
- interface
- {$i QuickLib.inc}
- uses
- SysUtils,
- {$IFDEF MSWINDOWS}
- Windows,
- Messages,
- WinSvc,
- {$ENDIF}
- {$IFNDEF FPC}
- System.IOUtils,
- {$ELSE}
- Quick.Files,
- {$ENDIF}
- Quick.Commons,
- Quick.Process;
- {$IFDEF MSWINDOWS}
- type
- TServiceState = (ssUnknow = -1,
- ssStopped = SERVICE_STOPPED,
- ssStartPending = SERVICE_START_PENDING,
- ssStopPending = SERVICE_STOP_PENDING,
- ssRunning = SERVICE_RUNNING,
- ssContinuePending = SERVICE_CONTINUE_PENDING,
- ssPausePending = SERVICE_PAUSE_PENDING,
- ssPaused = SERVICE_PAUSED);
- {$ENDIF}
- {$IFDEF MSWINDOWS}
- function ServiceIsPresent(const aServiceName : string): Boolean; overload;
- function ServiceIsPresent(const aMachine, aServiceName : string): Boolean; overload;
- function GetServicePath : string;
- function GetServiceState(const aServer, aServiceName : string) : TServiceState;
- function ServiceStart(const aServiceName : string) : Boolean; overload;
- function ServiceStop(const aServiceName : string ) : Boolean; overload;
- function ServiceStart(const aMachine, aServiceName : string) : Boolean; overload;
- function ServiceStop(const aMachine, aServiceName : string ) : Boolean; overload;
- {$ELSE}
- function ServiceIsPresent(const aServiceName : string): Boolean;
- function ServiceStart(const aServiceName : string) : Boolean;
- function ServiceStop(const aServiceName : string ) : Boolean;
- {$ENDIF}
- function ServiceUninstall(const aServiceName : string): Boolean;
- {$IFDEF MSWINDOWS}
- function DeleteServiceEx(svcName : string) : Boolean;
- {$ENDIF}
- implementation
- function ServiceIsPresent(const aServiceName : string) : Boolean;
- {$IFDEF MSWINDOWS}
- begin
- Result := ServiceIsPresent('localhost',aServiceName);
- end;
- {$ELSE}
- begin
- end;
- {$ENDIF}
- function ServiceStart(const aServiceName : string) : Boolean;
- {$IFDEF MSWINDOWS}
- begin
- Result := ServiceStart('localhost',aServiceName);
- end;
- {$ELSE}
- begin
- end;
- {$ENDIF}
- function ServiceStop(const aServiceName : string) : Boolean;
- {$IFDEF MSWINDOWS}
- begin
- Result := ServiceStop('localhost',aServiceName);
- end;
- {$ELSE}
- begin
- end;
- {$ENDIF}
- {$IFDEF MSWINDOWS}
- function ServiceIsPresent(const aMachine, aServiceName : string): Boolean;
- var
- smanHnd : SC_Handle;
- svchnd : SC_Handle;
- begin
- Result := False;
- smanHnd := OpenSCManager(PChar(aMachine), nil, SC_MANAGER_CONNECT);
- if (smanHnd > 0) then
- begin
- try
- svcHnd := OpenService(smanHnd, PChar(aServiceName), SERVICE_QUERY_STATUS);
- if svcHnd > 0 then
- begin
- Result := True;
- CloseServiceHandle(svchnd);
- end;
- finally
- CloseServiceHandle(smanHnd);
- end;
- end
- else raise Exception.CreateFmt('GetServiceState failed: %s',[GetLastOSError]);
- end;
- function GetServicePath : string;
- var
- filename : array[0..255] of Char;
- begin
- GetModuleFileName(hInstance,filename,255);
- Result := TPath.GetDirectoryName(filename);
- end;
- function GetServiceState(const aServer, aServiceName : string) : TServiceState;
- var
- svcStatus : TServiceStatus;
- smanHnd : SC_Handle;
- svcHnd : SC_Handle;
- begin
- Result := TServiceState.ssUnknow;
- smanHnd := OpenSCManager(PChar(aServer), Nil, SC_MANAGER_ALL_ACCESS);
- if smanHnd > 0 then
- begin
- try
- svcHnd := OpenService(smanHnd, PChar(aServiceName), SERVICE_ALL_ACCESS);
- if svcHnd > 0 then
- try
- if not QueryServiceStatus(svcHnd,svcStatus) then raise Exception.CreateFmt('GetServiceState failed: %s',[GetLastOSError]);
- Result := TServiceState(svcStatus.dwCurrentState);
- finally
- CloseServiceHandle(svcHnd);
- end;
- finally
- CloseServiceHandle(smanHnd);
- end;
- end
- else raise Exception.CreateFmt('GetServiceState failed: %s',[GetLastOSError]);
- end;
- function ServiceStart(const aMachine, aServiceName : string) : Boolean;
- var
- smanHnd : SC_HANDLE;
- svcHnd : SC_HANDLE;
- svcStatus : TServiceStatus;
- {$IFDEF FPC}
- psTemp : LPPCSTR;
- {$ELSE}
- psTemp : PChar;
- {$ENDIF}
- dwChkP : DWord;
- begin
- svcStatus.dwCurrentState := 0;
- smanHnd := OpenSCManager(PChar(aMachine),nil,SC_MANAGER_CONNECT);
- if smanHnd > 0 then
- begin
- try
- svcHnd := OpenService(smanHnd,PChar(aServiceName),SERVICE_START or SERVICE_QUERY_STATUS);
- if svcHnd > 0 then
- try
- psTemp := nil;
- if StartService(svcHnd,0,psTemp) then
- begin
- if QueryServiceStatus(svcHnd,svcStatus) then
- begin
- while svcStatus.dwCurrentState = SERVICE_START_PENDING do
- begin
- dwChkP := svcStatus.dwCheckPoint;
- Sleep(svcStatus.dwWaitHint);
- if not QueryServiceStatus(svcHnd,svcStatus) then Break;
- if svcStatus.dwCheckPoint < dwChkP then Break;
- end;
- end;
- end;
- finally
- CloseServiceHandle(svcHnd);
- end;
- finally
- CloseServiceHandle(smanHnd);
- end;
- end
- else raise Exception.CreateFmt('GetServiceState failed: %s',[GetLastOSError]);
- Result := SERVICE_RUNNING = svcStatus.dwCurrentState;
- end;
- function ServiceStop(const aMachine, aServiceName : string ) : Boolean;
- var
- smanHnd : SC_HANDLE;
- svcHnd : SC_HANDLE;
- svcStatus : TServiceStatus;
- dwChkP : DWord;
- begin
- smanHnd := OpenSCManager(PChar(aMachine),nil,SC_MANAGER_CONNECT);
- if smanHnd > 0 then
- try
- svcHnd := OpenService(smanHnd,PChar(aServiceName),SERVICE_STOP or SERVICE_QUERY_STATUS);
- if svcHnd > 0 then
- try
- if ControlService(svcHnd,SERVICE_CONTROL_STOP,svcStatus) then
- begin
- if QueryServiceStatus(svcHnd,svcStatus) then
- begin
- while svcStatus.dwCurrentState <> SERVICE_STOPPED do
- begin
- dwChkP := svcStatus.dwCheckPoint;
- Sleep(svcStatus.dwWaitHint);
- if not QueryServiceStatus(svcHnd,svcStatus) then Break;
- if svcStatus.dwCheckPoint < dwChkP then Break;
- end;
- end;
- end;
- finally
- CloseServiceHandle(svcHnd);
- end;
- finally
- CloseServiceHandle(smanHnd);
- end;
- Result := SERVICE_STOPPED = svcStatus.dwCurrentState;
- end;
- {$ENDIF}
- function ServiceUninstall(const aServiceName : string): Boolean;
- {$IFDEF MSWINDOWS}
- var
- smanHnd : SC_Handle;
- svchnd : SC_Handle;
- strMachineName: String;
- begin
- strMachineName := 'localhost';
- smanHnd := OpenSCManager(PChar(strMachineName), nil, SC_MANAGER_CONNECT);
- if smanHnd > 0 then
- begin
- try
- svchnd := OpenService(smanHnd, PChar(aServiceName), SERVICE_ALL_ACCESS or SERVICE_STOP);
- if svchnd > 0 then
- begin
- try
- {$IFDEF FPC}
- DeleteServiceEx(aServiceName);
- {$ELSE}
- WinSVC.DeleteService(svchnd);
- {$ENDIF}
- Result := True;
- finally
- CloseServiceHandle(svchnd);
- end;
- end
- else if svchnd = 0 Then
- Result := True
- else Result := False;
- finally
- CloseServiceHandle(smanHnd);
- end;
- end;
- end;
- {$ELSE}
- begin
- end;
- {$ENDIF}
- {$IFDEF MSWINDOWS}
- function DeleteServiceEx(svcName : string) : Boolean;
- begin
- Result := False;
- if ShellExecuteAndWait('open','sc','stop '+svcName,'',0,True) = 0 then
- begin
- Result := ShellExecuteAndWait('open','sc','delete '+svcName,'',0,True) = 0;
- end;
- end;
- {$ENDIF}
- end.
|