Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

ShellExecute program problem

Status
Not open for further replies.

konLao

Programmer
Mar 10, 2003
61
US
Dear FoxPro Programmers,
My FoxPro App. uses shellexecute to call PKUNZIP. It works fine. The problem is I need my Application to wait until PKUNZIP finish his job before it proceed. Does anyone know the solution to this.

Thank you,
KonLao
 
Here is VB code that does what you want, modify to use with VFP...

Private Declare Function OpenProcess Lib "kernel32" _
(ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As Long

Private Declare Function GetExitCodeProcess
Lib "kernel32" _
(ByVal hProcess As Long, lpExitCode As Long) As Long

Private Declare Function CloseHandle Lib "kernel32" _
(ByVal hObject As Long) As Long

Private Const PROCESS_QUERY_INFORMATION = &H400
Private Const STATUS_PENDING = &H103&


Private Sub Command1_Click()

RunShell "c:\windows\notepad.exe"

End Sub


Private Sub RunShell(cmdline As String)

Dim hProcess As Long
Dim ProcessId As Long
Dim exitCode As Long

ProcessId = Shell(cmdline, 1)
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,
False, ProcessId)

Do

Call GetExitCodeProcess(hProcess, exitCode)
DoEvents

Loop While exitCode = STATUS_PENDING

Call CloseHandle(hProcess)

MsgBox "The shelled process " & cmdline & " has
ended."

End Sub
Slighthaze = NULL
 
Slighthaze,

Forgive me if I seem out of line here, but I think that since this is a VFP forum, it would have been more beneficial for the code to be researched, converted, and posted in VFP syntax rather than throwing the code out and assuming the individual would want, or for that matter, know how to convert it.
Dave S.
[cheers]
 
KonLao,
I use the Process.VCX from the UT ( to run PKZIP. On the home page of the UT, click on the Download picture on the left, and choose Visual FoxPro. Enter "api_apprun" in the Title box (without the quotes), and you should get back a link to:
"API_APPRUN in .VCX form February 22, 2003
This contains PROCESS.VCX - a visual class library for the API_APPRUN class described in the FAQ#7789 (API_APPRUN - Executable launch management class). The class gives the ability to run DOS and WinApps from inside VFP using the CreateProcess() API call, and allows you to wait on termination or return immediately, and allows you to examine the execution status and termination code from an executable run by the class. It takes care of managing the process and thread handles, removing some potent..."

Highly recommended!

Rick
 
It sounds like Rick's recommendation will do just what you want... I just finished the VB->VFP translation, so I guess I'll post it below, anyway.

( ps. DSummZZZ : Of course it would be better to post the code as VFP instead of VB, however it certainly takes some effort to go through the translation! You never know how much of a boost someone needs... )

Code:
FUNCTION WaitForProcess
LPARAMETERS pcCmdline
#DEFINE PROCESS_QUERY_INFORMATION  0x0400
#DEFINE STATUS_PENDING             0x0103

  Declare LONG OpenProcess in Win32Api  LONG dwDesiredAccess, LONG bInheritHandle LONG dwProcessId 
  Declare LONG GetExitCodeProcess in Win32Api LONG hProcess, LONG @lpExitCode
  Declare LONG CloseHandle in win32api LONG 
  DECLARE LONG GetLastError in Win32API
  DECLARE INTEGER CreateProcess IN win32api ; 
      STRING   lpApplicationName,; 
      STRING   lpCommandLine,; 
      INTEGER  lpProcessAttributes,; 
      INTEGER  lpThreadAttributes,; 
      INTEGER  bInheritHandles,; 
      INTEGER  dwCreationFlags,; 
      INTEGER  lpEnvironment,; 
      STRING   lpCurrentDirectory,; 
      STRING   lpStartupInfo,; 
      STRING @ lpProcessInformation 

  * typedef struct _STARTUPINFO { 
  *  DWORD   cb; 
  *  LPTSTR  lpReserved; 
  *  LPTSTR  lpDesktop; 
  *  LPTSTR  lpTitle; 
  *  DWORD   dwX; 
  *  DWORD   dwY; 
  *  DWORD   dwXSize; 
  *  DWORD   dwYSize; 
  *  DWORD   dwXCountChars; 
  *  DWORD   dwYCountChars; 
  *  DWORD   dwFillAttribute; 
  *  DWORD   dwFlags; 
  *  WORD    wShowWindow; 
  *  WORD    cbReserved2; 
  *  LPBYTE  lpReserved2; 
  *  HANDLE  hStdInput; 
  *  HANDLE  hStdOutput; 
  *  HANDLE  hStdError; 
  * } STARTUPINFO, *LPSTARTUPINFO;     
  
  * typedef struct _PROCESS_INFORMATION { 
  *  HANDLE hProcess; 
  *  HANDLE hThread; 
  *  DWORD dwProcessId; 
  *  DWORD dwThreadId; 
  * } PROCESS_INFORMATION;
  
  
  LOCAL hProcess, ProcessId, exitCode,err, lcDir, lcStartupInfo, lcProcInfo
  lcDir    = Set('defa')+curdir()
  exitCode = 0
  
    * typedef struct _STARTUPINFO { 
  *  DWORD   cb; 
  *  LPTSTR  lpReserved; 
  *  LPTSTR  lpDesktop; 
  *  LPTSTR  lpTitle; 
  *  DWORD   dwX; 
  *  DWORD   dwY; 
  *  DWORD   dwXSize; 
  *  DWORD   dwYSize; 
  *  DWORD   dwXCountChars; 
  *  DWORD   dwYCountChars; 
  *  DWORD   dwFillAttribute; 
  *  DWORD   dwFlags; 
  *  WORD    wShowWindow; 
  *  WORD    cbReserved2; 
  *  LPBYTE  lpReserved2; 
  *  HANDLE  hStdInput; 
  *  HANDLE  hStdOutput; 
  *  HANDLE  hStdError; 
  * } STARTUPINFO, *LPSTARTUPINFO;     

  * 54 = 4+4+4+4+4+4+4+4+4+4+2+2+4+2+2+2
  lcStartupInfo = Num2Dword(54)+Num2Dword(0)+Num2Dword(0)+Num2Dword(0);
                  +Num2Dword(0)+Num2Dword(0);
                  +Num2Dword(0)+Num2Dword(0);
                  +Num2Dword(0)+Num2Dword(0);
                  +Num2word(0)+Num2word(0);
                  +Num2Dword(0);
                  +Num2word(0)+Num2word(0)+Num2word(0)
                  
  
  * 2,2,4,4
  lcProcInfo = Num2Word(0)+Num2Word(0)+Num2DWord(0)+Num2DWord(0)
  err = CreateProcess( pccmdLine,pccmdLine,0,0,0,0,0,lcDir,@lcStartupInfo,@lcProcInfo )
  if Err=0
    RETURN -100000-GetLastError()
  endif
  
  hProcess = Buf2Word( lcProcInfo ) && Takes first 2 chars
  if hProcess=0
    RETURN -200000-GetLastError()
  endif
   
  * Don't need to look up process from ID, CreateProcess gave us the hProcess
  *hProcess2 = OpenProcess(PROCESS_QUERY_INFORMATION, .f., ProcessId)

  do while .T.
    * Returns 0 if there is an error
    err=GetExitCodeProcess(hProcess, @exitCode)
    if err=0
      ?"Handle=",hProcess
      RETURN -300000-GetLastError()
    endif
    DoEvents   
    ??"."
    if (exitCode = STATUS_PENDING) && Still Running
      LOOP
    endif
    EXIT
  enddo

  CloseHandle(hProcess)
  RETURN ExitCode
ENDFUNC


* * *
* dword is compatible with LONG
FUNCTION  num2dword (lnValue) 
#DEFINE m0       256 
#DEFINE m1     65536 
#DEFINE m2  16777216 
    LOCAL b0, b1, b2, b3 
    b3 = Int(lnValue/m2) 
    b2 = Int((lnValue - b3*m2)/m1) 
    b1 = Int((lnValue - b3*m2 - b2*m1)/m0) 
    b0 = Mod(lnValue, m0) 
RETURN Chr(b0)+Chr(b1)+Chr(b2)+Chr(b3) 
* * *
* dword is compatible with LONG
FUNCTION  num2word (lnValue) 
RETURN Chr(MOD(m.lnValue,256)) + CHR(INT(m.lnValue/256)) 
* * * 
FUNCTION  buf2word (lcBuffer) 
RETURN Asc(SUBSTR(lcBuffer, 1,1)) + ; 
    Asc(SUBSTR(lcBuffer, 2,1)) * 256 
* * *
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  
ENDFUNC  


PROCEDURE Test
RunShell( "c:\windows\notepad.exe" )
RETURN
 
Thank you every one trying to help. I have to admit that wgcs, slighthaze and rgbean is taliking over my head. I am still infant in VFP. Here is my code from thread184-470950
by GriffMG

FUNCTION UnZip
PARAMETERS m.FILENAME,m.DESTDIR
LOCAL LNRETVAL, LCOPERATION
LCOPERATION = "Open"
DECLARE INTEGER ShellExecute IN SHELL32.DLL ;
INTEGER handle,;
STRING @sFile,;
STRING @lp,;
STRING @DIR,;
STRING @dir1,;
INTEGER ncmd
LNRETVAL = SHELLEXECUTE(0, LCOPERATION, "Winzip",;
"-min -e "+m.FILENAME+" "+m.DESTDIR, "", 1)
RETURN(.F.)

Please help.

Thank you,

KonLao
 
If you take all the code from my post and put it in a file called "WaitForProcess.PRG"
then in your program Proc UnZip becomes:
Code:
FUNCTION UnZip
PARAMETERS m.FILENAME,m.DESTDIR
LOCAL lcPathToWinzip
  lcPathToWinzip = "C:\program files\winzip\winzip.exe" && or whatever... you really should specify the full path since it's not likely to be available in the DOS PATH
  WaitForProcess( lcPathToWinzip+" -min -e "+m.FILENAME+" "+m.DESTDIR )
RETURN(.F.)

I've never used the Process.VCX that Rick mentioned, so I can't tell you exactly how to use that, but it would be something like:

Code:
FUNCTION UnZip
PARAMETERS m.FILENAME,m.DESTDIR
LOCAL lcPathToWinzip, loX
  lcPathToWinzip = "C:\program files\winzip\winzip.exe"
  loX = NEWOBJECT( 'unzipClass','Process.vcx' )
  loX.LaunchProgram( lcPathToWinzip, " -min -e "+m.FILENAME+" "+m.DESTDIR )
RETURN(.F.)

Note that "unzipClass" and "LaunchProgram" are my guesses are are practically garanteed to be the wrong names, but the form would be something like that.
 
DSummZZZ,

I must agree with you...my only excuse was a time constraint I had at the time that I saw this thread and I knew I had some VB code that did what was asked for.

wgcs,
Thank you for taking the time. Nice job.

Konlao,
My apologies if I just further confused the issue for you. Slighthaze = NULL
 
wgcs,
Thank you very much for helping. It's very generious of you. Eventhough its not exactly what I can use for my app. I had to download Add-on program from and install in my Winzip folder.

In my code, I use old fashion "Run" command...
run "wzunzip -o Full_path_Zip_file Destination_directory"

Notice, there is no "/N" to make it wait for winzip to finish its job before my FoxPro app. can continue.

slighthaze,
Apologies accepted. You didn't confused me.

Thanks again,

KonLao
 
Sabaidee KonLao,

Glad to know there other Laos in this forum.
Keo
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top