Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Halt app while external program runs
Message
From
12/05/2004 12:00:09
 
General information
Forum:
Visual FoxPro
Category:
Coding, syntax & commands
Miscellaneous
Thread ID:
00903008
Message ID:
00903213
Views:
22
Here is another one that launces Adobe Reader (finds its location on the current drive or in the registry) and uses getexitcodeprocess instead of waitforsingleobject to determine when the program has finished running. You must have adobe reader installed for it work of course.
lcACORDdef = SYS(5)+SYS(2003)
hdir = 'c:\'
li_acordview = .T.	&& set for testing purposes only

DO DECLexewait

*--Look for the file in known locations

lcresult = Acrofind()

IF EMPTY(lcresult)

*--Look for AcroRd32.exe first in the registry

	lcresult = readregistrykey()
	IF OCCURS('"',lcresult)>0
		IF TYPE('lcresult')="C" .AND. !EMPTY(lcresult)
			m.cAppName=SUBSTR(lcresult,2,AT('"',lcresult,2)-2)
		ELSE
			m.cAppName = ''
		ENDIF
	ELSE
		m.cAppName = lcresult+"AcroRd32.Exe"
	ENDIF
ELSE
	m.cAppName = lcresult
ENDIF

IF FILE(m.cAppName)	&& AcroRd32.exe

	lcline = " /p /h "
	IF li_acordview	&& preview in acrobat reader so user can select printer by ctrl-p
		lcline = ""
	ENDIF

	SET DEFAULT TO LEFT(hdir,RAT("\",hdir)-1)
	lnpos=(RAT("\",m.cAppName)+1)	&& one position to the right of
	lcshort=''
	lcpath=''
	IF lnpos > 0
		lcshort = UPPER(SUBSTR(m.cAppName,lnpos))	&& grab from lnpos to end
		lcpath  = UPPER(LEFT(m.cAppName,RAT("\",m.cAppName)-1))			&& strip off the extension
	ENDIF

	IF !EMPTY(lcshort) .AND. !EMPTY(lcpath)
		lcpath = "'"+lcpath+"'"
		SET DEFAULT TO &lcpath
		llacordok = ExeWait(lcshort,lcline, lcpath)
	ELSE
		hdir = ""
		llacordok = ExeWait( m.cAppName, lcline, hdir)
	ENDIF

	IF !llacordok
		=MESSAGEBOX("Unable to print Acord Form.",0+16+4096,"ERROR")
	ELSE
		WAIT WINDOW "Finished Printing" NOWAIT
	ENDIF

	SET DEFAULT TO &lcACORDdef

ELSE
	=MESSAGEBOX('Unable to locate Acrobat Reader. Please install and try again',0+16+4096,'ERROR - Acrobat Reader Missing.')
ENDIF

DO RELexewait

WAIT WINDOW "Returned to VFP program.  Press anykey to exit."
RETURN


*----------------------------------------------------------------------
PROCEDURE DECLexewait  && load required dlls for exewait function

=ADLLS(dllarray)
IF ASCAN(dllarray,'CREATEPROCESS') = 0
	DECLARE INTEGER CreateProcess IN kernel32;
		INTEGER lpAppName, STRING lpCmdLine, INTEGER lpProcAttr,;
		INTEGER lpThrAttr, INTEGER bInhHandles, INTEGER dwCrFlags,;
		INTEGER lpEnvir, INTEGER lpCurDir, ;
		STRING @lpStInfo, STRING @lpProcInfo
ENDIF
IF ASCAN(dllarray,'GETLASTERROR') = 0
	DECLARE INTEGER GetLastError IN kernel32
ENDIF
IF ASCAN(dllarray,"CLOSEHANDLE") = 0
	DECLARE INTEGER CloseHandle IN kernel32 INTEGER hObject
ENDIF
IF ASCAN(dllarray,"GETEXITCODEPROCESS") = 0
	DECLARE INTEGER GetExitCodeProcess IN WIN32API INTEGER hProcess, INTEGER @lpExitCode
ENDIF
IF ASCAN(dllarray,"SLEEP") = 0
	DECLARE Sleep IN kernel32 INTEGER dwMilliseconds
ENDIF

RETURN

*----------------------------------------------------------------------
PROCEDURE RELexewait  && release dlls for exewait function

CLEAR DLLS CreateProcess
CLEAR DLLS GetLastError
CLEAR DLLS CloseHandle
CLEAR DLLS GetExitCodeProcess
CLEAR DLLS Sleep

RETURN

*-----------------------------------------------------------------------
*--Uses GetExitcodeProcess instead of waitforsingleobject
PROCEDURE  ExeWait (lcApp, lcCmdLine, lcdir)
PRIVATE lntimes
lntimes = 0
IF _VFP.AUTOYIELD = .F.
	llsetback = .T.
ELSE
	llsetback = .F.
ENDIF
_VFP.AUTOYIELD = .T.
PRIVATE lnclosepass
lnclosepass = 0
#DEFINE INFINITE  0xFFFFFFFF
LOCAL lcStartupInfo, lcProcInfo, hProcess, ;
	lnPrio, lnIBelieve1
lnIBelieve1 = 1   && Don't remember what that was
lnPrio = 32 && Priority of Process=Normal
lcStartupInfo = CHR(68) + REPLI(CHR(0), 67)
lcProcInfo = REPLI(CHR(0), 16)
IF CreateProcess(0, m.lcApp+" "+m.lcCmdLine+CHR(0), 0,0,;
		m.lnIBelieve1, m.lnPrio,;
		0, 0, @lcStartupInfo, @lcProcInfo) <> 0
* process and thread handles returned in ProcInfo structure
	hProcess = buf2dword(SUBSTR(lcProcInfo, 1,4))
	hThread = buf2dword(SUBSTR(lcProcInfo, 5,4))
* waiting until the termination of the program
	DOEVENTS
	IF !li_acordview						&& printing only
		DO stopadobe
	ELSE
		DO WHILE .T.
			exitcode = 0					&& initialize return value to 0
			= GetExitCodeProcess(hProcess, @exitcode)	&& try to obtain process exit code
			IF exitcode # 259				&& not still busy
				EXIT							&& fall out of loop
			ENDIF
			= Sleep (100)					&& wait .1 seconds
		ENDDO
	ENDIF
	= CloseHandle(hThread)
	= CloseHandle(hProcess)
ELSE
	IF llsetback
		_VFP.AUTOYIELD = .F.
	ENDIF
	RETURN .F.
ENDIF
IF llsetback
	_VFP.AUTOYIELD = .F.
ENDIF
RETURN

*----------------------------------------------------------------------
PROCEDURE stopadobe
PARAMETERS hThread

DECLARE Sleep IN kernel32 INTEGER dwMilliseconds
DO WHILE !Passwin('Password') .AND. lnclosepass < 10
	lnclosepass = lnclosepass + 1
	=Sleep(300)
ENDDO
=Sleep(5000)
*DECLARE INTEGER TerminateThread IN WIN32API INTEGER hThread, INTEGER uExitCode
*=TerminateThread(hThread,99)
*RETURN

LOCAL awin_apps, vfp_handle, ln_current_window,ln_window_count
* Dimension array awin_apps to store running apps
DIMENSION awin_apps[1,2]
* Initialize variable to store handle for current application
vfp_handle=0
* Declare API Functions
DECLARE INTEGER FindWindow ;
	IN win32api ;
	INTEGER nullpointer, ;
	STRING cwindow_name
DECLARE INTEGER GetWindow ;
	IN win32api ;
	INTEGER ncurr_window_handle, ;
	INTEGER ndirection
DECLARE INTEGER GetWindowText ;
	IN win32api ;
	INTEGER n_win_handle, ;
	STRING @ cwindow_title, ;
	INTEGER ntitle_length
* End of API function declarations
* Get handle for current application
vfp_handle=FindWindow(0,_SCREEN.CAPTION)
* Store handle of current app to a variable
ln_current_window=vfp_handle
* Initialize a count variable used to dimension array of running apps
ln_window_count=0
DO WHILE ln_current_window>0
*  Initialize variable to store application title
	lc_window_title=SPACE(255)
* Call to GetWindowText to fetch window caption
	ln_length=GetWindowText(ln_current_window, ;
		@lc_window_title,LEN(lc_window_title))
* Note that the lc_window_title variable is used as a buffer to
* receive text from the call to GetWindowText
	IF ln_length>0
		lc_window_title=STRTRAN(TRIM(lc_window_title),CHR(0),"")
	ELSE
		lc_window_title=""
	ENDIF
	IF ln_current_window>0 .AND. !EMPTY(lc_window_title)
* Increment the window count and re-dimension the array of running
* applications
		ln_window_count=ln_window_count+1
		DIMENSION awin_apps(ln_window_count,2)
		awin_apps[ln_Window_Count,1]=lc_window_title
		awin_apps[ln_Window_Count,2]=ln_current_window
	ENDIF
* Call to GetWindow to fetch handle of running applications.
	ln_current_window=GetWindow(ln_current_window,2)
ENDDO
PRIVATE it
FOR it = 1 TO ALEN(awin_apps,1)
	IF "Adobe" $ awin_apps(it,1)
		IF TYPE('awin_apps(it,2)')="N"
			=close2(awin_apps(it,2))
		ENDIF
	ENDIF
ENDFOR

RETURN .T.

*----------------------------------------------------------------------
FUNCTION Acrofind
PRIVATE WNetGetConnection, lpszLocalname, lpszRemoteName, ;
	sLen, Lni, DRIVE, Dtype, llfound, Lni
PRIVATE ARRAY afilesfound(1,3)
DIMENSION afilesfound(1,3)
afilesfound(1,1)=" "
llfound = .F.
Lni = 0
DECLARE INTEGER WNetGetConnection IN win32api ;
	STRING lpszLocalName,;
	STRING lpszRemoteName,;
	INTEGER @ lpchBuffer && Declare the external WNetGetConnection ;
	API FUNCTION
slpRemoteName = SPACE(254) && Initialize variables
sLen = LEN(slpRemoteName) && Initialize variables
*--Populate the one dimensional array with valid drive letters
FOR I = 1 TO 26 && Loop through drive letters A thru Z
	DRIVE = CHR(I + 64)
	Dtype = DRIVETYPE(DRIVE) && Determine drive type
	DO CASE
		CASE Dtype = 3 && Hard drives
			Lni=Lni+1
			DIMENSION adrivelist(Lni,3)
			adrivelist(Lni,1)=DRIVE
			adrivelist(Lni,2)=.F.
			adrivelist(Lni,3)=.F.
		CASE Dtype = 4 && Removable or network drives
			iSuccess = WNetGetConnection(DRIVE + ;
				":",@slpRemoteName,@sLen)
			IF iSuccess = 0
				Lni=Lni+1
				DIMENSION adrivelist(Lni,3)
				adrivelist(Lni,1)=DRIVE
				adrivelist(Lni,2)=.F.
				adrivelist(Lni,3)=.F.
			ENDIF
	ENDCASE
ENDFOR
llfound = .F.
FOR Lni = 1 TO ALEN(adrivelist,1)
	FOR ib = 10 TO 1 STEP -1
		lcacrofile = adrivelist(Lni,1)+":"+"\Program Files\Adobe\Acrobat "+ALLTRIM(STR(ib))+".0\Reader\AcroRd32.Exe"
		IF FILE(lcacrofile)
			llfound = .T.
			EXIT
		ENDIF
	ENDFOR
	IF llfound
		EXIT
	ENDIF
ENDFOR

CLEAR DLLS WNetGetConnection

IF llfound
	RETURN lcacrofile
ELSE
	RETURN ''
ENDIF

*----------------------------------------------------------------------
FUNCTION buf2dword(lcBuffer)

RETURN ASC(SUBSTR(lcBuffer, 1,1)) + ;
	ASC(SUBSTR(lcBuffer, 2,1)) * 256 +;
	ASC(SUBSTR(lcBuffer, 3,1)) * 65536 +;
	ASC(SUBSTR(lcBuffer, 4,1)) * 16777216

*----------------------------------------------------------------------
FUNCTION readregistrykey

#DEFINE HKEY_CLASSES_ROOT           -2147483648
#DEFINE HKEY_CURRENT_USER           -2147483647
#DEFINE HKEY_LOCAL_MACHINE          -2147483646
#DEFINE HKEY_USERS                  -2147483645

#DEFINE REG_SZ 				1	&& String
#DEFINE REG_BINARY 			3	&& Binary data
#DEFINE REG_DWORD 			4	&& 32bits int

#DEFINE ERROR_SUCCESS		0	&& OK

*Start of Code
LOCAL nKey, cSubKey, cValue, cValueRead
nKey = HKEY_LOCAL_MACHINE
cSubKey = "Software\Microsoft\Windows\CurrentVersion\App Paths\AcroRd32.exe"
cValue = "Path"

cValueRead = ReadREG_SZ(nKey, cSubKey, cValue)
IF EMPTY(cValueRead)
	cValueRead = ''
ENDIF

RETURN cValueRead

*----------------------------------------------------------------------
FUNCTION ReadREG_SZ
* This function reads a REG_SZ value from the registry. If successful,
* it will return the value read. If not successful, it will return an empty string.
PARAMETERS  nKey, cSubKey, cValue
* nKey The root key to open. It can be any of the constants defined below.
*  #DEFINE HKEY_CLASSES_ROOT           -2147483648
*  #DEFINE HKEY_CURRENT_USER           -2147483647
*  #DEFINE HKEY_LOCAL_MACHINE          -2147483646
*  #DEFINE HKEY_USERS                  -2147483645
* cSubKey The SubKey to open.
* cValue The value that is going to be read.

* Constants that are needed for Registry functions
*   #DEFINE REG_SZ   1

* WIN 32 API functions that are used
DECLARE INTEGER RegOpenKey IN Win32API ;
	INTEGER nHKey, STRING @cSubKey, INTEGER @nResult
DECLARE INTEGER RegQueryValueEx IN Win32API ;
	INTEGER nHKey, STRING lpszValueName, INTEGER dwReserved,;
	INTEGER @lpdwType, STRING @lpbData, INTEGER @lpcbData
DECLARE INTEGER RegCloseKey IN Win32API INTEGER nHKey

* Local variables used
LOCAL nErrCode      && Error Code returned from Registry functions
LOCAL nKeyHandle    && Handle to Key that is opened in the Registry
LOCAL lpdwValueType && Type of Value that we are looking for
LOCAL lpbValue      && The data stored in the value
LOCAL lpcbValueSize && Size of the variable
LOCAL lpdwReserved  && Reserved Must be 0

* Initialize the variables
nKeyHandle = 0
lpdwReserved = 0
lpdwValueType = REG_SZ
lpbValue = ""

nErrCode = RegOpenKey(nKey, cSubKey, @nKeyHandle)
* If the error code isn't 0, then the key doesn't exist or can't be opened.
IF (nErrCode # 0) THEN
	RETURN ""
ENDIF

lpcbValueSize = 1
* Get the size of the data in the value
nErrCode=RegQueryValueEx(nKeyHandle, cValue, lpdwReserved, @lpdwValueType, @lpbValue, @lpcbValueSize)

* Make the buffer big enough
lpbValue = SPACE(lpcbValueSize)
nErrCode=RegQueryValueEx(nKeyHandle, cValue, lpdwReserved, @lpdwValueType, @lpbValue, @lpcbValueSize)

=RegCloseKey(nKeyHandle)

CLEAR DLLS RegOpenKey
CLEAR DLLS RegQueryValueEx
CLEAR DLLS RegCloseKey

IF (nErrCode # 0) THEN
	RETURN ""
ENDIF

lpbValue = LEFT(lpbValue, lpcbValueSize - 1)
RETURN lpbValue
.·*´¨)
.·`TCH
(..·*

010000110101001101101000011000010111001001110000010011110111001001000010011101010111001101110100
"When the debate is lost, slander becomes the tool of the loser." - Socrates
Vita contingit, Vive cum eo. (Life Happens, Live With it.)
"Life is not measured by the number of breaths we take, but by the moments that take our breath away." -- author unknown
"De omnibus dubitandum"
Previous
Reply
Map
View

Click here to load this message in the networking platform