|
@@ -0,0 +1,235 @@
|
|
|
+{ ***************************************************************************
|
|
|
+
|
|
|
+ Copyright (c) 2016-2018 Kike Pérez
|
|
|
+
|
|
|
+ Unit : Quick.Service
|
|
|
+ Description : Service functions
|
|
|
+ Author : Kike Pérez
|
|
|
+ Version : 1.0
|
|
|
+ Created : 14/07/2017
|
|
|
+ Modified : 14/03/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
|
|
|
+
|
|
|
+uses
|
|
|
+ System.SysUtils,
|
|
|
+ Winapi.Windows,
|
|
|
+ Winapi.WinSvc,
|
|
|
+ Winapi.Messages,
|
|
|
+ System.IOUtils,
|
|
|
+ Quick.Commons,
|
|
|
+ Quick.Process;
|
|
|
+
|
|
|
+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);
|
|
|
+
|
|
|
+ function ServiceIsPresent(const aMachine, aServiceName : string): Boolean;
|
|
|
+ function GetServicePath : string;
|
|
|
+ function GetServiceState(const aServer, aServiceName : string) : TServiceState;
|
|
|
+ function ServiceStart(const aMachine, aServiceName : string) : Boolean;
|
|
|
+ function ServiceStop(const aMachine, aServiceName : string ) : Boolean;
|
|
|
+ function ServiceUninstall(const aServiceName : string): Boolean;
|
|
|
+ function DeleteServiceEx(svcName : string) : Boolean;
|
|
|
+
|
|
|
+implementation
|
|
|
+
|
|
|
+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;
|
|
|
+ psTemp : PChar;
|
|
|
+ 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_RUNNING 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;
|
|
|
+
|
|
|
+function ServiceUninstall(const aServiceName : string): Boolean;
|
|
|
+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
|
|
|
+ Winapi.WinSVC.DeleteService(svchnd);
|
|
|
+ Result := True;
|
|
|
+ finally
|
|
|
+ CloseServiceHandle(svchnd);
|
|
|
+ end;
|
|
|
+ end
|
|
|
+ else if svchnd = 0 Then
|
|
|
+ Result := True
|
|
|
+ else Result := False;
|
|
|
+ finally
|
|
|
+ CloseServiceHandle(smanHnd);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+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;
|
|
|
+
|
|
|
+end.
|