News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Blocking ShellExecute?

Started by Mark Jones, July 10, 2005, 06:46:10 PM

Previous topic - Next topic

Mark Jones

Hi gang. If I invoke ShellExecute to run a second app, does ShellExecute block? If I do this:


    invoke ShellExecute,hWnd,0,addr lpMyFile,addr lpMyFileParams,0,SW_SHOW
    invoke Sleep,100                        ; needed to let above complete
    invoke VerifyWritten,addr lpOutputFile  ; was the new file created?


A sleep is needed to prevent the verify routine from returning a false "file not there" response. Problem is, the ShellExecute might take a lot longer to complete than 100ms.

VerifyWritten is:


VerifyWritten proc lpLocation:DWORD
LOCAL hFile:DWORD

    invoke CreateFile,lpLocation,GENERIC_READ,\  ; test for file exist
           0,0,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,0
    mov hFile,eax
    invoke GetLastError             ; does file exist?
    test eax,eax                    ; if so, eax will be 0
    jz @F
    invoke MessageBox,hWnd,lpLocation,addr szVerifyErr,MB_OK
@@:
    invoke CloseHandle,hFile
    ret                             ; end procedure
VerifyWritten endp


Is there a way to block on ShellExecute? Thanks.
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

Rifleman

Mark,
What do you think about setting up a polling loop using the 'exist' procedure from m32lib?  Once the file is created, it will tell you.

Quote
exist

exist proc lpszFileName:DWORD

Description
This function tests if a file exists at the path and file name in the zero terminated string.

Parameter

1.   lpszFileName The zero terminated string that has the path & name of the file to test.

Return Value
If the return value in eax is zero, the file does not exist, if it is 1, then it exists.

hth,
Paul

James Ladd

Mark,
Im not sure what you are doing is the right approach.
There is a lot that can go wrong with ShellExecute and your routine get the right results all the time.
I suggest the piping the shell output to a stdin and reading from it or there is another approach
that was posted here some time ago. It did a pipe thing.
I think you should also take the return code from ShellExecute into account as well.
Rgs, striker

hutch--

Mark,

Its a reasonably common problem because of the lazy write characteristic of the file system and the asynchronous nature of running applications. A couple of things, I would be inclined to use CreateProcess() instead because you can get more control over it and in this context it may be worth having a look at WaitForMultipleObjects() to test for file IO as well as application termination.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Mark Jones

Thanks! Yes it's a work in progress. The Exist proc works nicely and makes the code much more legible. :) Might as well give it away... this is part of a Win32 DLL to INC/LIB converter. Eventually I'll open a thread in the Workshop for beta testing. It works now (with a portion of Vortex's DLL2INC code) but I'm researching ways of calculating the argument count of arbitrary DLL exports (to build INVOKE-able libraries instead of SYSCALL types.)
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

sluggy

Quote from: Mark Jones
Hi gang.
Hi!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Quote from: Mark JonesIf I invoke ShellExecute to run a second app, does ShellExecute block?
It blocks until the process is started. Check here for the list of error codes it can return.


QuoteA sleep is needed to prevent the verify routine from returning a false "file not there" response. Problem is, the ShellExecute might take a lot longer to complete than 100ms.
<snip>
Is there a way to block on ShellExecute? Thanks.
Yes you can, but you have to code it manually, currently you are doing this in the wrong way. There are three different ways you could implement this:
- instead of spawning a new process, do *all* the work in a new thread. This is only good if you are in control of all the code, including the app that you are spawning
- create a wait or watch: watch for something like directory contents changing with FindFirstChangeNotification, or wait on the process (handle) using WaitForSingleObjectEx
 - combine the above two approaches: put the VerifyWritten code in a thread, it can continuously poll/wait/watch while the main thread continues, and then just signal back to the main thread either when the job completes or a specified time elapses.

Option 3 is the best as it combines maximum flexibility and usability, and is ideal if you are spawning a third party application which you have very little control over.