*CallWindowsService.prg LPARAMETERS tcService,tcAction #DEFINE SERVICE_WIN32 0x30 #DEFINE SERVICE_RUNNING 4 _vfp.aUTOYIELD=.t. SET ESCAPE ON ON ESCAPE SET PROCEDURE TO WINDOWSSERVICECLASS.PRG additive LOCAL ws As winservices, srv As winservice STORE 1 TO tnAnimate STORE "" TO lcCurrentStatus, lcStatus DO WHILE m.lcCurrentStatus = m.lcStatus ws = CREATEOBJECT("winservices", Null, Null, SERVICE_WIN32) srv = ws.GetService(m.tcService) IF ISNULL(srv) ? m.tcService + " service is not found on this computer" EXIT ENDIF if m.tnAnimate=1 m.tnAnimate=2 m.tcAnimate="|" else m.tnAnimate=1 m.tcAnimate="-" endif DO case CASE m.tcAction="START" m.lcCurrentStatus="stopped" srv.StartService() CASE m.tcAction="STOP" m.lcCurrentStatus="running" srv.StopService() CASE m.tcAction="PAUSE" m.lcCurrentStatus=IIF(srv.currentstate=SERVICE_RUNNING,"running", "stopped") srv.PauseService() CASE m.tcAction="STATUS" ENDCASE WAIT WINDOW NOWAIT NOCLEAR m.tcService + " service is being " + m.tcAction + IIF(m.tcAction='STOP','P','') + 'ED ' + m.tcAnimate m.lcStatus=IIF(srv.currentstate=SERVICE_RUNNING,"running", "stopped") FASTDOEVENTS() srv=.NULL. ws=.NULL. ENDDO WAIT WINDOW NOWAIT m.tcService + " service is " + m.lcStatus + "." RETURN m.lcStatus FUNCTION FastDoEvents KEYBOARD " " =INKEY() DOEVENTS RETURNThe WindowsService Class definition is in WindowsServiceClass.prg
DEFINE CLASS winservices As Collection #DEFINE SC_MANAGER_CONNECT 1 #DEFINE SC_MANAGER_LOCK 8 #DEFINE SC_MANAGER_ENUMERATE_SERVICE 4 #DEFINE SERVICE_ACTIVE 1 #DEFINE SERVICE_INACTIVE 2 #DEFINE SERVICE_DRIVER 0x0b #DEFINE SERVICE_WIN32 0x30 #DEFINE SERVICE_STOPPED 1 #DEFINE SERVICE_RUNNING 4 #DEFINE SERVICE_PAUSED 7 #DEFINE SERVICE_START 0x10 #DEFINE SERVICE_STOP 0x20 #DEFINE SERVICE_PAUSE_CONTINUE 0x40 #DEFINE SERVICE_INTERROGATE 0x80 #DEFINE SERVICE_CONTROL_STOP 1 #DEFINE SERVICE_CONTROL_PAUSE 2 #DEFINE SERVICE_CONTROL_INTERROGATE 4 PROTECTED hManager, hLock hManager=0 hLock=0 errorcode=0 PROCEDURE Init(cComputerName, cDatabaseName, nServiceType) THIS.declare IF VARTYPE(m.cComputerName) <> "C" cComputerName=Null ENDIF IF VARTYPE(m.cDatabaseName) <> "C" cDatabaseName=Null ENDIF THIS.hManager = OpenSCManager(m.cComputerName, m.cDatabaseName,; BITOR(SC_MANAGER_CONNECT, SC_MANAGER_LOCK,; SC_MANAGER_ENUMERATE_SERVICE)) THIS.errorcode = IIF(THIS.hManager=0, GetLastError(), 0) IF VARTYPE(m.nServiceType)="N" THIS.EnumServices(m.nServiceType) ENDIF PROCEDURE EnumServices(nServiceType) #DEFINE ENUM_SERVICE_STATUS_SIZE 36 #DEFINE SERVICE_STATUS_SIZE 28 THIS.ClearEnum LOCAL nBufsize, nBytesNeeded, nCount, hResume, nServiceStatus STORE 0 TO nBytesNeeded, nCount, hResume nServiceStatus = BITOR(SERVICE_ACTIVE, SERVICE_INACTIVE) = EnumServicesStatus(THIS.hManager, nServiceType,; nServiceStatus, 0, 0,; @nBytesNeeded, @nCount, @hResume) nBufsize = nBytesNeeded hBuffer = LocalAlloc(0, nBufsize) hResume = 0 = EnumServicesStatus(THIS.hManager, nServiceType,; nServiceStatus, hBuffer, nBufsize,; @nBytesNeeded, @nCount, @hResume) LOCAL cBuffer, cService, nIndex, hPtr, hServiceName cBuffer = REPLICATE(CHR(0), nBufsize) = MemToStr(@cBuffer, hBuffer, nBufsize) FOR nIndex=0 TO nCount-1 LOCAL oService As winservice oService = CREATEOBJECT("winservice",; THIS, m.hBuffer, @cBuffer, nIndex) THIS.Add(oService, oService.servicename) oService=Null NEXT = LocalFree(hBuffer) RETURN .T. PROCEDURE Destroy IF THIS.hManager <> 0 THIS.ClearEnum THIS.UnlockDatabase = CloseServiceHandle(THIS.hManager) THIS.hManager=0 ENDIF FUNCTION GetService(vService) As winservice LOCAL oService As winservice, ex As Exception TRY oService = THIS.Item(vService) CATCH TO ex THIS.errorcode = ex.Message oService = Null ENDTRY RETURN oService PROTECTED PROCEDURE ClearEnum DO WHILE THIS.Count > 0 LOCAL itm As winservice itm = THIS.Item(1) itm = Null THIS.Remove(1) ENDDO FUNCTION GetHManager() RETURN THIS.hManager FUNCTION IsDatabaseLocked RETURN (THIS.hLock <> 0) FUNCTION LockDatabase IF THIS.hLock = 0 THIS.hLock = LockServiceDatabase(THIS.hManager) ENDIF THIS.errorcode = IIF(THIS.hLock=0, GetLastError(), 0) RETURN (THIS.hLock <> 0) FUNCTION UnlockDatabase IF THIS.hLock <> 0 = UnlockServiceDatabase(THIS.hLock) THIS.hLock = 0 ENDIF RETURN (THIS.hLock = 0) PROTECTED PROCEDURE declare DECLARE INTEGER GetLastError IN kernel32 DECLARE INTEGER LockServiceDatabase IN advapi32 INTEGER hSCManager DECLARE INTEGER CloseServiceHandle IN advapi32 INTEGER hSCObject DECLARE INTEGER UnlockServiceDatabase IN advapi32 INTEGER ScLock DECLARE INTEGER LocalFree IN kernel32 INTEGER hMem DECLARE RtlMoveMemory IN kernel32 As StrToMem; INTEGER Dest, STRING @Src, INTEGER nLength DECLARE RtlMoveMemory IN kernel32 As MemToStr; STRING @dest, INTEGER src, INTEGER nLength DECLARE INTEGER LocalAlloc IN kernel32; INTEGER uFlags, INTEGER uBytes DECLARE INTEGER OpenSCManager IN advapi32; STRING lpMachineName, STRING lpDatabaseName,; LONG dwDesiredAccess DECLARE INTEGER OpenService IN advapi32; INTEGER hSCManager, STRING lpServiceName,; LONG dwDesiredAccess DECLARE INTEGER EnumServicesStatus IN advapi32; INTEGER hSCManager, LONG dwServiceType, LONG dwServiceState,; INTEGER lpServices, LONG cbBufSize, LONG @pcbBytesNeeded,; LONG @lpServicesReturned, LONG @lpResumeHandle DECLARE INTEGER StartService IN advapi32; INTEGER hService, LONG dwNumServiceArgs,; INTEGER lpServiceArgVectors DECLARE INTEGER ControlService IN advapi32; INTEGER hService, LONG dwControl,; STRING @lpServiceStatus ENDDEFINE DEFINE CLASS winservice As Session PROTECTED oWinServices, hService hService=0 errorcode=0 servicename="" displayname="" servicetype=0 currentstate=0 controlsaccepted=0 win32exitcode=0 serviceexitcode=0 checkpoint=0 waithint=0 PROCEDURE Init(oWinServices, hBuffer, cBuffer, nIndex) THIS.oWinServices = m.oWinServices LOCAL cService, hPtr cService = SUBSTR(cBuffer,; (nIndex*ENUM_SERVICE_STATUS_SIZE)+1,; ENUM_SERVICE_STATUS_SIZE) THIS.ConvertStatusInfo(SUBSTR(cService, 9)) hPtr = buf2dword(SUBSTR(cService, 1,4)) - hBuffer + 1 THIS.servicename = THIS.GetName(@cBuffer, hPtr) hPtr = buf2dword(SUBSTR(cService, 5,4)) - hBuffer + 1 THIS.displayname = THIS.GetName(@cBuffer, hPtr) PROCEDURE Destroy THIS.CloseServiceHandle PROTECTED FUNCTION GetName(cBuffer, hPtr) IF (hPtr <= 0) OR hPtr >= LEN(cBuffer) RETURN "" ENDIF LOCAL cName, ch cName = "" DO WHILE hPtr < LEN(cBuffer) ch = SUBSTR(cBuffer, m.hPtr, 1) IF m.ch = CHR(0) EXIT ENDIF cName = cName + m.ch hPtr = hPtr + 1 ENDDO RETURN cName FUNCTION StartService * 1055=ERROR_SERVICE_DATABASE_LOCKED * A call to the StartService function to start a service * in a locked database fails. No other service control manager * functions are affected by a lock. THIS.errorcode = 0 IF NOT THIS.OpenServiceHandle(0x90) RETURN .F. ENDIF LOCAL LockStatus LockStatus = THIS.oWinServices.IsDatabaseLocked() IF THIS.oWinServices.UnlockDatabase() IF StartService(THIS.hService, 0,0) = 0 THIS.errorcode = GetLastError() ENDIF IF m.LockStatus THIS.oWinServices.LockDatabase ENDIF ENDIF THIS.CloseServiceHandle RETURN (THIS.errorcode <> 0) PROCEDURE StopService THIS.ControlService(SERVICE_STOP, SERVICE_CONTROL_STOP) PROCEDURE PauseService THIS.ControlService(SERVICE_PAUSE_CONTINUE, SERVICE_CONTROL_PAUSE) PROTECTED PROCEDURE CloseServiceHandle IF THIS.hService <> 0 = CloseServiceHandle(THIS.hService) THIS.hService = 0 ENDIF PROTECTED FUNCTION OpenServiceHandle(nAccess) THIS.CloseServiceHandle THIS.hService = OpenService(THIS.oWinServices.GetHManager(),; THIS.servicename, nAccess) THIS.errorcode = IIF(THIS.hService=0, 0, GetLastError()) RETURN (THIS.hService <> 0) PROTECTED FUNCTION ControlService(nOpenFlag, nCtrlFlag) THIS.errorcode = 0 IF NOT THIS.OpenServiceHandle(nOpenFlag) RETURN .F. ENDIF LOCAL cStatusInfo cStatusInfo = REPLICATE(CHR(0), SERVICE_STATUS_SIZE) IF ControlService(THIS.hService, nCtrlFlag, @cStatusInfo) = 0 THIS.errorcode = GetLastError() ENDIF THIS.CloseServiceHandle RETURN .T. FUNCTION UpdateStatusInfo THIS.errorcode = 0 IF NOT THIS.OpenServiceHandle(SERVICE_INTERROGATE) RETURN .F. ENDIF LOCAL cStatusInfo cStatusInfo = REPLICATE(CHR(0), SERVICE_STATUS_SIZE) IF ControlService(THIS.hService,; SERVICE_CONTROL_INTERROGATE, @cStatusInfo) = 0 THIS.errorcode = GetLastError() ELSE THIS.ConvertStatusInfo(cStatusInfo) ENDIF THIS.CloseServiceHandle RETURN .T. PROTECTED PROCEDURE ConvertStatusInfo(cStatusInfo) THIS.servicetype = buf2dword(SUBSTR(cStatusInfo, 1,4)) THIS.currentstate = buf2dword(SUBSTR(cStatusInfo, 5,4)) THIS.controlsaccepted = buf2dword(SUBSTR(cStatusInfo, 9,4)) THIS.win32exitcode = buf2dword(SUBSTR(cStatusInfo, 13,4)) THIS.serviceexitcode = buf2dword(SUBSTR(cStatusInfo, 17,4)) THIS.checkpoint = buf2dword(SUBSTR(cStatusInfo, 21,4)) THIS.waithint = buf2dword(SUBSTR(cStatusInfo, 25,4)) ENDDEFINE FUNCTION buf2dword(lcBuffer) RETURN Asc(SUBSTR(lcBuffer, 1,1)) + ; BitLShift(Asc(SUBSTR(lcBuffer, 2,1)), 8) +; BitLShift(Asc(SUBSTR(lcBuffer, 3,1)), 16) +; BitLShift(Asc(SUBSTR(lcBuffer, 4,1)), 24)