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

Problems with WaitForSingleObject and GetExitProcessCode

Status
Not open for further replies.

CFB

Programmer
Jan 11, 2001
74
US
I'm using Shell to execute a program and need to wait until the program has finished executing before continuing on with the rest of my code. I've tried using WaitForSingleObject WinAPI function and it caused the program I executed with my Shell command to freeze. Then I created a loop using the GetExitProcessCode WinAPI function and that bogged down the CPU so that the program that was being executed was running extremely slow. Has anyone else experienced this sort of problem with WaitForSingleObject or have another approach that I could use?

Does anyone know how to halt execution of your VB app for a certain amount of time? I'm looking into the Sleep WinAPI method right now, but haven't found any good examples on MSDN. If I could suspend execution of my program for a set amount of time that would remedy the situation as well. Thanks for all the help.
 
The sleep API will have problems since you can not be completely positive about how long the ither program is going to run (faster/slow processors, machine workload at any given time). Also, looping while looking for the exit code will put too much of a load on the CPU. The WaitForSingleObject API is the correct way to do this (I have used it several times myself) . . . I fon't know why it wouldn't work for you . . . did you use the OpenProcess (not CreateProcess) to get a handle with the correct rights? Post your code here so some of us can offer suggestions as to why it didn't work for you. - Jeff Marler B-)
 
Here's the code I used with the WaitForSingleObject API function.

ntaskid = Shell(cProgPath, 1)
nhandle = OpenProcess(SYNCHRONIZE, False, ntaskid)
WaitForSingleObject(nhandle, 0)

I'm trying to automate a Silk script. The script that Silk is running opens up a few other applications, so I'm not sure if that's causing the problem. The WaitForSingleObject is causing Silk to freeze.
 
You use a 0 for the timeout in the WaitForSingeObject . . . are aware that doing this will cause the API to only test the state and then return immediately? Here . . . this is directly from Microsoft . . .


Specifies the time-out interval, in milliseconds. The function returns if the interval elapses, even if the object's state is nonsignaled. If dwMilliseconds is zero, the function tests the object's state and returns immediately. If dwMilliseconds is INFINITE, the function's time-out interval never elapses.


I'm not sure if this is the action that you intended or not. If you want your app to wait, you should specify a real time or use the Infinite constant. - Jeff Marler B-)
 
That was a piece of test code that I was using. I put the 0 in so it would return immediately so that I could test if it was the WaitForSingleObject function that was causing the problem. Even with the 0 as the timeout value, my VB application and the program that I executed from within my VB app still freeze up.
 
Does the problem only happen when you are shelling the Silk Script? Or can you reproduce the error with any shelled application (like notepad for instance)? - Jeff Marler B-)
 
It seems to only be happening when I'm shelling the Silk Script.
 
I'm guessing that it has something to do with Silk Script and not your VB app or API calls. Is the app that you are trying to shell 16 bit? There is an article in MSDN about using WaitForSingleObject when shelling a 16 bit app. It states that in order to make it work, you need to perform a thunking operation. - Jeff Marler B-)
 
Yes I definitely agree it has something to do with the Silk Script and not VB or the API calls. Thunking is converting 16 bit to 32 bit correct? I'm looking up some articles on this right now, any sample code would be really helpful. Thanks once again for all the help.
 
It almost seems that the problem is that the WaitForSingleObject API function think that Silk is on the same thread as the VB application that is Shelling it. Not sure if that makes any sense, but that's my best guess. Anyone else ran into something like that?
 
Here is what I use on a daily basis to do synchronous shelling. I see a few differences between this and how you're using it. You already covered why you're not using infinite. Then there's the false instead of 0, but a false is zero in vb so that should work too. You say you use the line:
WaitForSingleObject(nhandle, 0)

But you can't call a function in VB using the parenthesis without assigning the return value to something. I tried changing the line:
WaitForSingleObject phnd, INFINITE
In my code below to:
WaitForSingleObject(phnd, INFINITE)
And it's immeadiately flagged as an error "= expected" or something like that. I'm not saying that's your error but this code might help you. Just put it in a standard module and call SyncShell instead of Shell. That will remove any doubt about whether or not you are using the API calls directly. Also, if you try to run this script from a command line what happens?
Oh yeah, when the script 'freezes' what is in the title bar of the window it is running in? The reason i added the "command.com /c " to the command line is that without it any programs i shelled to on Win95 machines would hang. when i made the dos window visible i saw that in the title bar it said Finished, it just wasn't closing the window. the /c tells it to close the window when it's done.

Code:
Option Explicit

'-------- API calls declaration ---------
Public Declare Sub Sleep Lib "kernel32" _
    (ByVal dwMilliseconds As Long)
    
Public Declare Function OpenProcess Lib "kernel32" _
    (ByVal dwDesiredAccess As Long, _
    ByVal bInheritHandle As Long, _
    ByVal dwProcessID As Long) As Long
    
Public Declare Function CloseHandle Lib "kernel32" _
    (ByVal hObject As Long) As Long
    
Public Declare Function WaitForSingleObject Lib "kernel32" _
    (ByVal hProcess As Long, _
    ByVal dwMilliseconds As Long) As Long

'---------------- global constants -------
Global Const INFINITE = &HFFFFFFFF
Global Const SYNCHRONIZED = &H100000

Public Sub SyncShell(ByVal sql As String, _
            Optional ByVal vbwindowmode As VbAppWinStyle = vbMinimizedFocus)
    Dim pid As Long
    Dim phnd As Long
    pid = Shell("command.com /c " & sql, vbwindowmode)
    If pid <> 0 Then
        phnd = OpenProcess(SYNCHRONIZED, 0, pid)
        If phnd <> 0 Then
            DoEvents
            WaitForSingleObject phnd, INFINITE
            CloseHandle phnd
            DoEvents
        End If
    End If
End Sub
Ruairi

Could your manufacturing facility benefit from real time process monitoring? Would you like your employees to be able to see up to the minute goal and actual production?
For innovative, low cost solutions check out my website.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top