Quick.Service.pas 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. { ***************************************************************************
  2. Copyright (c) 2016-2018 Kike Pérez
  3. Unit : Quick.Service
  4. Description : Service functions
  5. Author : Kike Pérez
  6. Version : 1.1
  7. Created : 14/07/2017
  8. Modified : 30/08/2018
  9. This file is part of QuickLib: https://github.com/exilon/QuickLib
  10. ***************************************************************************
  11. Licensed under the Apache License, Version 2.0 (the "License");
  12. you may not use this file except in compliance with the License.
  13. You may obtain a copy of the License at
  14. http://www.apache.org/licenses/LICENSE-2.0
  15. Unless required by applicable law or agreed to in writing, software
  16. distributed under the License is distributed on an "AS IS" BASIS,
  17. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. See the License for the specific language governing permissions and
  19. limitations under the License.
  20. *************************************************************************** }
  21. unit Quick.Service;
  22. interface
  23. {$i QuickLib.inc}
  24. uses
  25. SysUtils,
  26. Windows,
  27. {$IFNDEF FPC}
  28. Messages,
  29. WinSvc,
  30. System.IOUtils,
  31. {$ELSE}
  32. Quick.Files,
  33. {$ENDIF}
  34. Quick.Commons,
  35. Quick.Process;
  36. type
  37. TServiceState = (ssUnknow = -1,
  38. ssStopped = SERVICE_STOPPED,
  39. ssStartPending = SERVICE_START_PENDING,
  40. ssStopPending = SERVICE_STOP_PENDING,
  41. ssRunning = SERVICE_RUNNING,
  42. ssContinuePending = SERVICE_CONTINUE_PENDING,
  43. ssPausePending = SERVICE_PAUSE_PENDING,
  44. ssPaused = SERVICE_PAUSED);
  45. function ServiceIsPresent(const aMachine, aServiceName : string): Boolean;
  46. function GetServicePath : string;
  47. function GetServiceState(const aServer, aServiceName : string) : TServiceState;
  48. function ServiceStart(const aMachine, aServiceName : string) : Boolean;
  49. function ServiceStop(const aMachine, aServiceName : string ) : Boolean;
  50. function ServiceUninstall(const aServiceName : string): Boolean;
  51. function DeleteServiceEx(svcName : string) : Boolean;
  52. implementation
  53. function ServiceIsPresent(const aMachine, aServiceName : string): Boolean;
  54. var
  55. smanHnd : SC_Handle;
  56. svchnd : SC_Handle;
  57. begin
  58. Result := False;
  59. smanHnd := OpenSCManager(PChar(aMachine), nil, SC_MANAGER_CONNECT);
  60. if (smanHnd > 0) then
  61. begin
  62. try
  63. svcHnd := OpenService(smanHnd, PChar(aServiceName), SERVICE_QUERY_STATUS);
  64. if svcHnd > 0 then
  65. begin
  66. Result := True;
  67. CloseServiceHandle(svchnd);
  68. end;
  69. finally
  70. CloseServiceHandle(smanHnd);
  71. end;
  72. end
  73. else raise Exception.CreateFmt('GetServiceState failed: %s',[GetLastOSError]);
  74. end;
  75. function GetServicePath : string;
  76. var
  77. filename : array[0..255] of Char;
  78. begin
  79. GetModuleFileName(hInstance,filename,255);
  80. Result := TPath.GetDirectoryName(filename);
  81. end;
  82. function GetServiceState(const aServer, aServiceName : string) : TServiceState;
  83. var
  84. svcStatus : TServiceStatus;
  85. smanHnd : SC_Handle;
  86. svcHnd : SC_Handle;
  87. begin
  88. Result := TServiceState.ssUnknow;
  89. smanHnd := OpenSCManager(PChar(aServer), Nil, SC_MANAGER_ALL_ACCESS);
  90. if smanHnd > 0 then
  91. begin
  92. try
  93. svcHnd := OpenService(smanHnd, PChar(aServiceName), SERVICE_ALL_ACCESS);
  94. if svcHnd > 0 then
  95. try
  96. if not QueryServiceStatus(svcHnd,svcStatus) then raise Exception.CreateFmt('GetServiceState failed: %s',[GetLastOSError]);
  97. Result := TServiceState(svcStatus.dwCurrentState);
  98. finally
  99. CloseServiceHandle(svcHnd);
  100. end;
  101. finally
  102. CloseServiceHandle(smanHnd);
  103. end;
  104. end
  105. else raise Exception.CreateFmt('GetServiceState failed: %s',[GetLastOSError]);
  106. end;
  107. function ServiceStart(const aMachine, aServiceName : string) : Boolean;
  108. var
  109. smanHnd : SC_HANDLE;
  110. svcHnd : SC_HANDLE;
  111. svcStatus : TServiceStatus;
  112. {$IFDEF FPC}
  113. psTemp : LPPCSTR;
  114. {$ELSE}
  115. psTemp : PChar;
  116. {$ENDIF}
  117. dwChkP : DWord;
  118. begin
  119. svcStatus.dwCurrentState := 0;
  120. smanHnd := OpenSCManager(PChar(aMachine),nil,SC_MANAGER_CONNECT);
  121. if smanHnd > 0 then
  122. begin
  123. try
  124. svcHnd := OpenService(smanHnd,PChar(aServiceName),SERVICE_START or SERVICE_QUERY_STATUS);
  125. if svcHnd > 0 then
  126. try
  127. psTemp := nil;
  128. if StartService(svcHnd,0,psTemp) then
  129. begin
  130. if QueryServiceStatus(svcHnd,svcStatus) then
  131. begin
  132. while svcStatus.dwCurrentState = SERVICE_START_PENDING do
  133. begin
  134. dwChkP := svcStatus.dwCheckPoint;
  135. Sleep(svcStatus.dwWaitHint);
  136. if not QueryServiceStatus(svcHnd,svcStatus) then Break;
  137. if svcStatus.dwCheckPoint < dwChkP then Break;
  138. end;
  139. end;
  140. end;
  141. finally
  142. CloseServiceHandle(svcHnd);
  143. end;
  144. finally
  145. CloseServiceHandle(smanHnd);
  146. end;
  147. end
  148. else raise Exception.CreateFmt('GetServiceState failed: %s',[GetLastOSError]);
  149. Result := SERVICE_RUNNING = svcStatus.dwCurrentState;
  150. end;
  151. function ServiceStop(const aMachine, aServiceName : string ) : Boolean;
  152. var
  153. smanHnd : SC_HANDLE;
  154. svcHnd : SC_HANDLE;
  155. svcStatus : TServiceStatus;
  156. dwChkP : DWord;
  157. begin
  158. smanHnd := OpenSCManager(PChar(aMachine),nil,SC_MANAGER_CONNECT);
  159. if smanHnd > 0 then
  160. try
  161. svcHnd := OpenService(smanHnd,PChar(aServiceName),SERVICE_STOP or SERVICE_QUERY_STATUS);
  162. if svcHnd > 0 then
  163. try
  164. if ControlService(svcHnd,SERVICE_CONTROL_STOP,svcStatus) then
  165. begin
  166. if QueryServiceStatus(svcHnd,svcStatus) then
  167. begin
  168. while svcStatus.dwCurrentState <> SERVICE_STOPPED do
  169. begin
  170. dwChkP := svcStatus.dwCheckPoint;
  171. Sleep(svcStatus.dwWaitHint);
  172. if not QueryServiceStatus(svcHnd,svcStatus) then Break;
  173. if svcStatus.dwCheckPoint < dwChkP then Break;
  174. end;
  175. end;
  176. end;
  177. finally
  178. CloseServiceHandle(svcHnd);
  179. end;
  180. finally
  181. CloseServiceHandle(smanHnd);
  182. end;
  183. Result := SERVICE_STOPPED = svcStatus.dwCurrentState;
  184. end;
  185. function ServiceUninstall(const aServiceName : string): Boolean;
  186. var
  187. smanHnd : SC_Handle;
  188. svchnd : SC_Handle;
  189. strMachineName: String;
  190. begin
  191. strMachineName := 'localhost';
  192. smanHnd := OpenSCManager(PChar(strMachineName), nil, SC_MANAGER_CONNECT);
  193. if smanHnd > 0 then
  194. begin
  195. try
  196. svchnd := OpenService(smanHnd, PChar(aServiceName), SERVICE_ALL_ACCESS or SERVICE_STOP);
  197. if svchnd > 0 then
  198. begin
  199. try
  200. {$IFDEF FPC}
  201. DeleteServiceEx(aServiceName);
  202. {$ELSE}
  203. WinSVC.DeleteService(svchnd);
  204. {$ENDIF}
  205. Result := True;
  206. finally
  207. CloseServiceHandle(svchnd);
  208. end;
  209. end
  210. else if svchnd = 0 Then
  211. Result := True
  212. else Result := False;
  213. finally
  214. CloseServiceHandle(smanHnd);
  215. end;
  216. end;
  217. end;
  218. function DeleteServiceEx(svcName : string) : Boolean;
  219. begin
  220. Result := False;
  221. if ShellExecuteAndWait('open','sc','stop '+svcName,'',0,True) = 0 then
  222. begin
  223. Result := ShellExecuteAndWait('open','sc','delete '+svcName,'',0,True) = 0;
  224. end;
  225. end;
  226. end.