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 gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

ShellExecute - How to check when it's stopped. 4

Status
Not open for further replies.

gbettle

Programmer
Nov 23, 2005
33
DK
Howdy all,

Hope this email finds everyone well.

Would anyone know how to check with ShellExecute has stopped?

I'm spawning a cmd box that's running a Blat script. However, I want VFP to stop processing until this window is finished\gone

A work around has been giving to me already:

> Put something in the final step of the batch file that creates a "flag"
> file and then check for the existence of that flag file in VFP. Don't
> forget to erase that flag file at the very beginning of the batch run so
> as to not get a false reading from a previous run.
>

What I would really like to do is something like the following:

DECLARE INTEGER ShellExecute IN shell32.dll ;
INTEGER hndWin, ;
STRING cAction, ;
STRING cFileName, ;
STRING cParams, ;
STRING cDir, ;
INTEGER nShowWin

DECLARE INTEGER GetWindowInfo IN user32;
INTEGER hwnd,;
STRING @ pwi

cAction = "open"
lnResult = ShellExecute( 0, cAction, tcFile, "", "", 2)

lnRunning = GetWindowInfo( lnWindow, pwi)
do while lnRunning > 0
lnRunning = GetWindowInfo( lnWindow, pwi)
enddo

NB: from
"If ShellExecute() succeeds, it returns an integer greater than 32. The integer is in fact the handle of the main window of the application which has been launched."

My problem is that lnRunning is always returning 0.

Any ideas?

Many thanks!

Cheers,

Garry
 
Garry,

When calling GetWindowInfo, you need to pass pwi by reference:

lnRunning = GetWindowInfo( lnWindow, @pwi)

Because you weren't doing that, the function was returning 0 (to indicate an error), so your loop never executed.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

My Visual FoxPro site: www.ml-consult.co.uk
 
The man himself! Great website by the way.

Hi Mike,

Thanks for the quick reply.

I'm still getting 0 from the following:

pwi = ""

cAction = "open"
lnWindow = ShellExecute( 0, cAction, tcFile, "", "", 2)

lnRunning = GetWindowInfo( lnWindow, @pwi)
do while lnRunning > 0
lnRunning = GetWindowInfo( lnWindow, @pwi)
enddo
 
First ShellExecute doesn't returns hWnd, Here what it returns from MSDN library:

Returns a value greater than 32 if successful, or an error value that is less than or equal to 32 otherwise. The following table lists the error values. The return value is cast as an HINSTANCE for backward compatibility with 16-bit Windows applications. It is not a true HINSTANCE, however. The only thing that can be done with the returned HINSTANCE is to cast it to an int and compare it with the value 32 or one of the error codes below.

So you can't use it return value for GetWindowInfo() as hWnd.


Borislav Borissov
VFP9 SP1, SQL Server 2000/2005.
 
Hi Borislav,

Thanks for the reply - I was beginning to suspect such a thing was happening.

Is there any other method of spawning a new process, with a proper hWnd that's returned?

Cheers,

Garry


 

Garry,

I've always worked on the assumption that, if the returned value from ShellExecute()is > 32, then it's a window handle. But I'll look into it in more detail, and I'll correct the article if I'm wrong.

As a separate issue, when calling GetWindowInfo(), the buffer - that is, the second parameter - needs to be at least 60 bytes long. Since it's being passed by reference, the function will overwrite it with the data that it wants to return to the caller. By setting pwi to an empty string, you risk overwriting other parts of your application's memory.

In other words, instead of:

pwi = ""

you should do:

pwi = replicate(chr(0), 60)

But I don't think that explains the behaviour you are seeing.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

My Visual FoxPro site: www.ml-consult.co.uk
 
Garry,

Just to follow up my previous post .... I've found several documents that say that, if the returned value is >32, then it's an instance handle, not a window handle as I originally thought.

For information on how to find a window handle from an instance handle, see:

However, that looks quite complicated, given the requirements.

For a different approach, if you know the caption of the window, you could loop through all the open windows, checking to see if the window in question exists. I've got some sample code for that at:

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

My Visual FoxPro site: www.ml-consult.co.uk
 
However, I want VFP to stop processing until this window is finished\gone

Then you need something like this:

Code:
LPARAMETERS tcFileName
#DEFINE INFINITE  0xFFFFFFFF 

LOCAL ARRAY laJunk[1]
LOCAL lnRes, lcStartupInfo, lcProcInfo, lnHandle

*** Load DLLs if necessary
lnRes = ADLLS( laJunk )
IF lnRes = 0 OR  NOT ( ASCAN( laJunk, 'GetLastError', 1, -1, 1, 15 ) > 0)
  *** We don't have the function available
  DECLARE INTEGER GetLastError IN kernel32 
ENDIF
IF lnRes = 0 OR  NOT ( ASCAN( laJunk, 'CloseHandle', 1, -1, 1, 15 ) > 0)  
  DECLARE INTEGER CloseHandle IN kernel32 INTEGER nHandle
ENDIF 
IF lnRes = 0 OR  NOT ( ASCAN( laJunk, 'CreateProcess', 1, -1, 1, 15 ) > 0)  
  DECLARE INTEGER CreateProcess IN kernel32; 
          STRING lpAppName, STRING lpCmdLine, INTEGER lpProcAttr,; 
          INTEGER lpThrAttr, INTEGER bInhHandles, INTEGER dwCrFlags,; 
          INTEGER @lpEnvir, STRING lpCurDir, STRING lpStInfo,; 
          STRING @lpProcInfo 
ENDIF
IF lnRes = 0 OR  NOT ( ASCAN( laJunk, 'WaitForSingleObject', 1, -1, 1, 15 ) > 0)  
  DECLARE INTEGER WaitForSingleObject IN kernel32; 
          INTEGER hHandle, INTEGER dwMilliseconds 
ENDIF

***  The STARTUPINFO structure is used with the CreateProcess, 
***  CreateProcessAsUser, and CreateProcessWithLogonW functions 
***  to specify the window station, desktop, standard handles, 
***  and appearance of the main window for the new process.
lcStartupInfo = CHR(68) + REPLICATE(CHR(0), 67) 

*** The PROCESS_INFORMATION structure is filled in 
*** by the CreateProcess function with information 
*** about a newly created process and its primary thread.
lcProcInfo = REPLICATE(CHR(0), 16) 

IF CreateProcess( tcFileName, '', 0,0,0,0,0, CURDIR(),; 
                  lcStartupInfo, @lcProcInfo) # 0 

  *** retrieve handle for the new process by converting
  *** the first four bytes in the structure to a DWORD
  lnHandle = ASC(SUBSTR(lcProcInfo, 1, 1 ) ) + ; 
             ASC(SUBSTR(lcProcInfo, 2, 1 ) ) * 256 + ; 
             ASC(SUBSTR(lcProcInfo, 3, 1 ) ) * 256^2 + ; 
             ASC(SUBSTR(lcProcInfo, 4, 1 ) ) * 256^3 

  *** Now wait until it is finished
  WaitForSingleObject ( lnHandle, INFINITE ) 
  CloseHandle( lnHandle ) 
ELSE 
  MESSAGEBOX( 'Unable to Create Process' + CHR( 13 ) +;
              "Error code: " + TRANSFORM( GetLastError() ), 16, 'Major WAAHHHHH!!!!' )
ENDIF


Marcia G. Akins
 
Hi Marcia,

Many thanks.

Unfortunately, I'm still having problems.

I run your code with a tcFilename of "File 1 20060517 145219.BAT", which contains:

ftp -i -d -s:"File 1 20060517 145219.FTP" ***.***.***.*** >> "File 1 20060517 145219.LOG"

It doesn't throw the error message, but it flys-by the whole process, and doesn't run the ftp command.

Any ideas?

Cheers,

Garry
 
I run your code with a tcFilename of "File 1 20060517 145219.BAT", which contains:

The code I gave you can not be used to run a batch file.

Instead of using ShellExecute, why don't you get one of several freely available FTP classes so you can control the entire process yourself from VFP?



Marcia G. Akins
 
Many Thanks Everyone,

FTP classes here I come!

Cheers,

Garry
 

Garry,

Here's one more option to add your list:

Code:
oWSH = CREATEOBJECT("wscript.shell")
oWSH.Run("SomeApplication", 3, .T.)
  && 3 is the window state, .T. means
  && suspend VFP until the target app
  && has finished.

Is that any use?

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

My Visual FoxPro site: www.ml-consult.co.uk
 
Hi Mike,

Many thanks for the wscript.shell idea.

It seems to work ok, but only if the filename to run doesn't have spaces in it.

i.e. This works fine:

"?:\???\???????\????????\T00QQHSH.BAT"

This doesn't. It returns "OLE error code 0x80070002: The system cannot find the file specified":

"?:\???\???????\????????\???????????? 20060518 122240.BAT"

I've checked, with a line before your code ( if file( tcfilename) ) and the BAT file does exist.

Garry

"If at first you don't succeed, skydiving isn't for you.
 
Many thanks Mike,

I've changed my file format by replacing " " with "_":

"?:\???\???????\????????\????????????_20060518_122240.BAT"

and it works. Strange, but it works.

Cheers,

Garry
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top