Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Start/Stop Spooler and wait it out
Message
De
30/08/2019 17:09:59
Mike Yearwood
Toronto, Ontario, Canada
 
 
À
28/08/2019 14:26:59
Mike Yearwood
Toronto, Ontario, Canada
Information générale
Forum:
Visual FoxPro
Catégorie:
Fonctions Windows API
Divers
Thread ID:
01670394
Message ID:
01670485
Vues:
55
I made the routine work with a counter. After 10 tries I recreated the ws and srv objects, but then I found this:

https://docs.microsoft.com/en-us/windows/win32/services/svccontrol-cpp.

I'll be translating/reworking that to VFP.

>VFP 9 SP2, remoting to a development virtual machine.
>
>I grabbed a copy of the code from GitHub - thanks to Anatoliy for posting it - and am attempting to use a loop to determine when the service changed to the status I requested.
>
>It seems I have to release both the WS and SRV objects to get accurate results. It's slow. So my "animation" doesn't animate quickly, but it does detect that the service stopped/started.
>
>I tried to keep the WS object and release+recreate the srv object inside the loop, but it never seems to detect that Windows has started or stopped the service. I cannot use recursion, because it can take a long time to start the spooler.
>
>What can I do to get accurate results from the srv object without reinstantiating both?
>
>I'm calling CallWindowsService.prg like so.
>?CallWindowsService("Spooler","STOP")
>?CallWindowsService("Spooler","START")
>
>
>*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
>RETURN
>
>
>
>The 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)  
>
Précédent
Répondre
Fil
Voir

Click here to load this message in the networking platform