Quick.Service.pas 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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.0
  7. Created : 14/07/2017
  8. Modified : 14/03/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. uses
  24. System.SysUtils,
  25. Winapi.Windows,
  26. Winapi.WinSvc,
  27. Winapi.Messages,
  28. System.IOUtils,
  29. Quick.Commons,
  30. Quick.Process;
  31. type
  32. TServiceState = (ssUnknow = -1,
  33. ssStopped = SERVICE_STOPPED,
  34. ssStartPending = SERVICE_START_PENDING,
  35. ssStopPending = SERVICE_STOP_PENDING,
  36. ssRunning = SERVICE_RUNNING,
  37. ssContinuePending = SERVICE_CONTINUE_PENDING,
  38. ssPausePending = SERVICE_PAUSE_PENDING,
  39. ssPaused = SERVICE_PAUSED);
  40. function ServiceIsPresent(const aMachine, aServiceName : string): Boolean;
  41. function GetServicePath : string;
  42. function GetServiceState(const aServer, aServiceName : string) : TServiceState;
  43. function ServiceStart(const aMachine, aServiceName : string) : Boolean;
  44. function ServiceStop(const aMachine, aServiceName : string ) : Boolean;
  45. function ServiceUninstall(const aServiceName : string): Boolean;
  46. function DeleteServiceEx(svcName : string) : Boolean;
  47. implementation
  48. function ServiceIsPresent(const aMachine, aServiceName : string): Boolean;
  49. var
  50. smanHnd : SC_Handle;
  51. svchnd : SC_Handle;
  52. begin
  53. Result := False;
  54. smanHnd := OpenSCManager(PChar(aMachine), nil, SC_MANAGER_CONNECT);
  55. if (smanHnd > 0) then
  56. begin
  57. try
  58. svcHnd := OpenService(smanHnd, PChar(aServiceName), SERVICE_QUERY_STATUS);
  59. if svcHnd > 0 then
  60. begin
  61. Result := True;
  62. CloseServiceHandle(svchnd);
  63. end;
  64. finally
  65. CloseServiceHandle(smanHnd);
  66. end;
  67. end
  68. else raise Exception.CreateFmt('GetServiceState failed: %s',[GetLastOSError]);
  69. end;
  70. function GetServicePath : string;
  71. var
  72. filename : array[0..255] of Char;
  73. begin
  74. GetModuleFileName(hInstance,filename,255);
  75. Result := TPath.GetDirectoryName(filename);
  76. end;
  77. function GetServiceState(const aServer, aServiceName : string) : TServiceState;
  78. var
  79. svcStatus : TServiceStatus;
  80. smanHnd : SC_Handle;
  81. svcHnd : SC_Handle;
  82. begin
  83. Result := TServiceState.ssUnknow;
  84. smanHnd := OpenSCManager(PChar(aServer), Nil, SC_MANAGER_ALL_ACCESS);
  85. if smanHnd > 0 then
  86. begin
  87. try
  88. svcHnd := OpenService(smanHnd, PChar(aServiceName), SERVICE_ALL_ACCESS);
  89. if svcHnd > 0 then
  90. try
  91. if not QueryServiceStatus(svcHnd,svcStatus) then raise Exception.CreateFmt('GetServiceState failed: %s',[GetLastOSError]);
  92. Result := TServiceState(svcStatus.dwCurrentState);
  93. finally
  94. CloseServiceHandle(svcHnd);
  95. end;
  96. finally
  97. CloseServiceHandle(smanHnd);
  98. end;
  99. end
  100. else raise Exception.CreateFmt('GetServiceState failed: %s',[GetLastOSError]);
  101. end;
  102. function ServiceStart(const aMachine, aServiceName : string) : Boolean;
  103. var
  104. smanHnd : SC_HANDLE;
  105. svcHnd : SC_HANDLE;
  106. svcStatus : TServiceStatus;
  107. psTemp : PChar;
  108. dwChkP : DWord;
  109. begin
  110. svcStatus.dwCurrentState := 0;
  111. smanHnd := OpenSCManager(PChar(aMachine),nil,SC_MANAGER_CONNECT);
  112. if smanHnd > 0 then
  113. begin
  114. try
  115. svcHnd := OpenService(smanHnd,PChar(aServiceName),SERVICE_START or SERVICE_QUERY_STATUS);
  116. if svcHnd > 0 then
  117. try
  118. psTemp := nil;
  119. if StartService(svcHnd,0,psTemp) then
  120. begin
  121. if QueryServiceStatus(svcHnd,svcStatus) then
  122. begin
  123. while svcStatus.dwCurrentState <> SERVICE_RUNNING do
  124. begin
  125. dwChkP := svcStatus.dwCheckPoint;
  126. Sleep(svcStatus.dwWaitHint);
  127. if not QueryServiceStatus(svcHnd,svcStatus) then Break;
  128. if svcStatus.dwCheckPoint < dwChkP then Break;
  129. end;
  130. end;
  131. end;
  132. finally
  133. CloseServiceHandle(svcHnd);
  134. end;
  135. finally
  136. CloseServiceHandle(smanHnd);
  137. end;
  138. end
  139. else raise Exception.CreateFmt('GetServiceState failed: %s',[GetLastOSError]);
  140. Result := SERVICE_RUNNING = svcStatus.dwCurrentState;
  141. end;
  142. function ServiceStop(const aMachine, aServiceName : string ) : Boolean;
  143. var
  144. smanHnd : SC_HANDLE;
  145. svcHnd : SC_HANDLE;
  146. svcStatus : TServiceStatus;
  147. dwChkP : DWord;
  148. begin
  149. smanHnd := OpenSCManager(PChar(aMachine),nil,SC_MANAGER_CONNECT);
  150. if smanHnd > 0 then
  151. try
  152. svcHnd := OpenService(smanHnd,PChar(aServiceName),SERVICE_STOP or SERVICE_QUERY_STATUS);
  153. if svcHnd > 0 then
  154. try
  155. if ControlService(svcHnd,SERVICE_CONTROL_STOP,svcStatus) then
  156. begin
  157. if QueryServiceStatus(svcHnd,svcStatus) then
  158. begin
  159. while svcStatus.dwCurrentState <> SERVICE_STOPPED do
  160. begin
  161. dwChkP := svcStatus.dwCheckPoint;
  162. Sleep(svcStatus.dwWaitHint);
  163. if not QueryServiceStatus(svcHnd,svcStatus) then Break;
  164. if svcStatus.dwCheckPoint < dwChkP then Break;
  165. end;
  166. end;
  167. end;
  168. finally
  169. CloseServiceHandle(svcHnd);
  170. end;
  171. finally
  172. CloseServiceHandle(smanHnd);
  173. end;
  174. Result := SERVICE_STOPPED = svcStatus.dwCurrentState;
  175. end;
  176. function ServiceUninstall(const aServiceName : string): Boolean;
  177. var
  178. smanHnd : SC_Handle;
  179. svchnd : SC_Handle;
  180. strMachineName: String;
  181. begin
  182. strMachineName := 'localhost';
  183. smanHnd := OpenSCManager(PChar(strMachineName), nil, SC_MANAGER_CONNECT);
  184. if smanHnd > 0 then
  185. begin
  186. try
  187. svchnd := OpenService(smanHnd, PChar(aServiceName), SERVICE_ALL_ACCESS or SERVICE_STOP);
  188. if svchnd > 0 then
  189. begin
  190. try
  191. Winapi.WinSVC.DeleteService(svchnd);
  192. Result := True;
  193. finally
  194. CloseServiceHandle(svchnd);
  195. end;
  196. end
  197. else if svchnd = 0 Then
  198. Result := True
  199. else Result := False;
  200. finally
  201. CloseServiceHandle(smanHnd);
  202. end;
  203. end;
  204. end;
  205. function DeleteServiceEx(svcName : string) : Boolean;
  206. begin
  207. Result := False;
  208. if ShellExecuteAndWait('open','sc','stop '+svcName,'',0,True) = 0 then
  209. begin
  210. Result := ShellExecuteAndWait('open','sc','delete '+svcName,'',0,True) = 0;
  211. end;
  212. end;
  213. end.