Shellexecute to launch VFP app from another VFP app

Traitée Shellexecute to launch VFP app from another VFP app

  • Saturday, June 02, 2012 1:06 AM
     
     

    I think this is fairly simple but I can't seem to get the syntax correct.

    I want to launch a vfp app passing 4 parameters. 

    The parameters are variables that contain information such as the folder location, username, password etc.

    The problem is I am not sure how to build the paramter string.

     mparam = '"'+parm1+'",'+'"'+parm2+'",'+'"'+parm3+'",'+'"'+parm4+'"'

     declare integer ShellExecute in shell32.dll ;
            integer hndWin, ;
            string cAction, ;
            string cFileName, ;
            string cParams, ;
            string cDir, ;
            integer nShowWin
            nerror = ShellExecute(0,'open','myvfp.exe',mparam,"",1)

    Any help greatly appreciated.

    Stuart

All Replies

  • Saturday, June 02, 2012 5:19 AM
    Answerer
     
     Answered

    Hi Stuart,

    Check below link there is sample given for How to Pass Parameter to VFP Exe.

    http://www.berezniker.com/content/pages/visual-foxpro/how-pass-parameters-vfp-exe

    hth

    Kalpesh


    Please "Mark as Answer" if this post answered your question. :)

    Kalpesh Chhatrala | Software Developer | Rajkot | India

    Kalpesh 's Blog

    VFP Form to C#, Vb.Net Conversion Utility

  • Monday, June 04, 2012 6:49 AM
    Answerer
     
      Has Code

    Hi Stuart,

    although Sergeys blog as mentioned in Kalpeshs answer is always an excellent source I want to add some alternative ways on how to start another exe from within your app (instead of SHELLEXECUTE).

    The way how to call another exe depends on what your first app shall do during the called exe is running.

    So....using Sergeys description about converting the params to strings and assuming, that your app shall continue working (=2 parallel running exe where you can switch with ALT+TAB) you can do something like this:

    TEXT TO lcRun TEXTMERGE NOSHOW PRETEXT 1+2+4+8
        RUN /N my2ndapp.exe <<liIntegerVal>> <<lcCharVal>>
    ENDTEXT 
    &lcRun

    However, if you want to take care, that your 1. exe will stop working until the called exe was closed, then you might use a routine I found some years ago. I can't give credit to the original programmer of that code because I don't remember where it came from.

    ADDED:

    I found the source once more: Code comes from the late Ed Rauh and can be found on UT!

    So part 1 shows how to call the function (param 3 know 4 different values: HIDE,NOR,MIN,MAX) :

    lcFile	= [my2ndapp.exe]
    lcPara	= TRANSFORM( liIntegerVal ) ;
    	+ ALLTRIM( lcStringVal )
    lcDir	= SYS( 5 ) + SYS( 2003 )
    LaunchExeAndWait(lcFile + [ ] + lcPara,lcDir,[NOR])

    and here comes the function:

    FUNCTION LaunchExeAndWait
    LPARAMETERS pcCommandLine, puFromDir, pcWindowMode
    
    *	pcCommandLine			(R) - command line to launch
    *	puFromDir				(O) - Run from directory (default - CWD)
    *	pcWindowMode			(O)	- Start Application Window mode, one of (HIDE, MIN, MAX, NOR)
    *								  (default - default setting of application)
    
    *	Returns:
    *	0 = CreateProcess didn't start what was asked
    *	1 = Process ran to completion
    *	-1= Process started but user aborted wait.  Danger - app is still running AFAIK
    
    #DEFINE cnINFINITE 		0xFFFFFFFF
    #DEFINE cnHalfASecond	500	&& milliseconds
    #DEFINE cnTimedOut		0x0102
    
    *	We need some API calls, declare here
    
    *	GetCurrentProcess() returns the pseudohandle of the current process
    DECLARE INTEGER GetCurrentProcess IN WIN32API AS GetCurrProc
    
    *	WaitForIdleInput() waits until the target process is idle for input
    DECLARE INTEGER WaitForInputIdle IN WIN32API AS WaitInpIdle ;
    	INTEGER nProcessHandle, ;
    	INTEGER nWaitForDuration
    
    *	WaitForSingleObject() waits until the handle in parm 1 is signalled 
    *	or the timeout period expires
    DECLARE INTEGER WaitForSingleObject IN WIN32API AS WaitOnAppExit ;
    	INTEGER hProcessHandle, ;
    	INTEGER dwTimeOut
    
    *	This API call does the work.  The parameters are as follows:
    *		lpszModuleName - ptr-> file name of module to execute.  Since we aren't launching .CPLs, do not use
    *		lpszCommandLine - ptr-> command to execute, as passed to us
    *		lpSecurityAttributesProcess - ptr-> SECURITY_ATTRIBUTES structure for Process.  Pass a null pointer
    *		lpSecurityAttributesThread - ptr-> SECURITY_ATTRIBUTES structure for first thread.  Pass a null pointer
    *		bInheritHandles - whether or not chlid inherits parent handles.  Since no SECURITY_ATTRIBUTES passed, default to FALSE
    *		dwCreateFlags - Process Creation Mode flag set.  We use the default mode at normal priority, ie 0
    *		lpvEnvironment	- ptr-> a set of environment strings as if a MULTI_SZ.  We don't set, so pass a null pointer
    *		lpszStartupDir - ptr-> the starting directory.  If none provided to us, pass a null pointer
    *		lpStartInfo - ptr-> a STARTUPINFO structure.  We use one structure member at times.
    *		lpProcessInfo - ptr-> a PROCESS_INFORMATION structure, used to return PID/PHANDLE detail.  
    *						We use one member on return
    DECLARE SHORT CreateProcess IN WIN32API AS CrPr ;
    	STRING lpszModuleName, ;
    	STRING @lpszCommandLine, ;
    	STRING lpSecurityAttributesProcess, ;
    	STRING lpSecurityAttributesThread, ;
    	SHORT bInheritHandles, ;
    	INTEGER dwCreateFlags, ;
    	STRING lpvEnvironment, ;
    	STRING lpszStartupDir, ;
    	STRING @lpStartInfo, ;
    	STRING @lpProcessInfo
    
    IF TYPE('pcCommandLine') # 'C'
    	*	Command line must be a character string
    	RETURN 0
    ENDIF
    
    IF TYPE('puFromDir') # 'C'
    	*	If not a character string, pass a null pointer, defaulting to Current Working Dir
    	puFromDir = 0
    ELSE
    	*	Otherwise, null pad the string
    	puFromDir = puFromDir + CHR(0)
    ENDIF
    
    IF TYPE('pcWindowMode') # 'C'
    	*	If not passed, set to null string
    	pcWindowMode = ''
    ELSE
    	*	Translate the passed window mode to uppercase
    	pcWindowMode = UPPER(pcWindowMode)
    ENDIF
    
    LOCAL nStartedProcessHandle, uResult, cProcessInfo, cStartUpInfo
    
    *	Make default Structures for the CreateProcess call
    *
    *	ProcessInfo - 4 bytes, a Process handle, a Thread Handle, a (DWORD) ProcessId and a (DWORD) ThreadID
    *					we save the Process handle and return it to caller in tnReturnProcessHandle
    
    cProcessInfo = REPL(CHR(0),16)
    
    *	StartUpInfo is a 68 byte long complex structure;  we either have 68 bytes with a cb member (byte 1) 68
    *	or with cb of 68, dwFlag low order byte (byte 45) of 1, and low order byte wShowWindow (byte 49) set to
    *	the SW_ value appropriate for the Window Mode desired.
    
    DO CASE
    CASE pcWindowMode = 'HIDE'
    
    	*	Hide - use STARTF_USESHOWFLAG and value of 0
    	cStartUpInfo = CHR(68) + ;
    					REPL(CHR(0),43) + ;
    					CHR(1) + ;
    					REPL(CHR(0),23)
    
    CASE pcWindowMode = 'NOR'
    
    	*	Normal - use STARTF_USESHOWFLAG and value of 1
    	cStartUpInfo = CHR(68) + ;
    					REPL(CHR(0),43) + ;
    					CHR(1) + ;
    					REPL(CHR(0),3) + ;
    					CHR(1) + ;
    					REPL(CHR(0),19)
    
    CASE pcWindowMode = 'MIN'
    
    	*	Minimize - use STARTF_USESHOWFLAG and value of 2
    	cStartUpInfo = CHR(68) + ;
    					REPL(CHR(0),43) + ;
    					CHR(1) +  ;
    					REPL(CHR(0),3) + ;
    					CHR(2) + ;
    					REPL(CHR(0),19)
    
    CASE pcWindowMode = 'MAX'
    
    	*	Maximize - use STARTF_USESHOWFLAG and value of 3
    	cStartUpInfo = CHR(68) + ;
    					REPL(CHR(0),43) + ;
    					CHR(1) +  ;
    					REPL(CHR(0),3) + ;
    					CHR(3) + ;
    					REPL(CHR(0),19)
    					
    *	Other options exist - see WINBASE.H for values
    OTHERWISE
    
    	*	Use default of application
    	cStartUpInfo = CHR(68) + REPL(CHR(0),67)
    
    ENDCASE
    
    *	Do it now!
    uResult = CrPr(	0, ;
    				pcCommandLine, ;
    				0, 0, 0, 0, 0, ;
    				puFromDir, ;
    				@cStartUpInfo, ;
    				@cProcessInfo)
    
    IF uResult = 1
    
    	*	CreateProcess() started our app, but we have to wait until it finishes loading
    	*	Strip the process handle from the PROCESS_INFORMATION structure
    	nStartedProcessHandle = (((ASC(SUBST(cProcessInfo,4,1))*256) + ;
    								ASC(SUBST(cProcessInfo,3,1)))*256 + ;
    								ASC(SUBST(cProcessInfo,2,1)))*256 + ;
    								ASC(LEFT(cProcessInfo,1))
    
    	*	It's been launched;  wait until we're idling along
    	=WaitInpIdle(GetCurrProc(),cnINFINITE)
    
    	*	As long as the other process exists, wait for it
    	DO WHILE WaitOnAppExit(nStartedProcessHandle, cnHalfASecond) = cnTimedOut
    
    		*	Give us an out in case the other app hangs - lets the user quit via <Esc>
    		IF INKEY() = 27
    			*	Still running but we aren't waiting - return a -1 as a warning
    			uResult = -1
    			EXIT
    		ENDIF
    
    	ENDDO
    
    ELSE
    	*	Return 0 to indicate failure
    	uResult = 0
    ENDIF
    
    RETURN uResult
    


    Gruss / Best regards -Tom 010101100100011001010000011110000101001001101111011000110110101101110011


  • Monday, June 04, 2012 9:10 PM
     
     

    The article explained everything I needed.  Spaces and not commas as separators was my big problem.

    Greatly appreciated!

    Stuart

  • Monday, June 04, 2012 9:11 PM
     
     

    I will review the code, I really appreciate the response!

    Stuart