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

Synchronic Shell Function 2

Status
Not open for further replies.

Naftali

Programmer
Feb 14, 2001
17
0
0
IL
Hi All,

I'm looking for a function that executes a program -like the Shell function- but I need one that will activate it synchronic (i.e. that I will have to wait till the other program completes its work) and to get a return code back.

The similar function in C is spawnl().

Does anyone know what's the similar in VB?

Thanks in Advance,

Naftali.
 
Naftali,

I have encountered this problem in a number of my VB projects and I do not believe there is a function that provides a simple solution. "Shell" (unfortunately) is asynchronous; here is how I have solved it in a number of my projects (what follows is an example that merely demonstrates the technique):

1. I started with a form that would contain all of the code that would execute up to and including the Shell.

2. I added a timer control to the form with the "enabled" property set to False and the "interval" property set to 5000 (5 seconds). Obviously, you can use a different interval based on what you're waiting for; e.g., if you expect the shelled program to run for an hour then use 60000 (60 seconds).

3. The last two lines of code on the form should execute the Shell and then change the "enabled" property of the timer to True.

4. The timer control only has one event (the Timer event) which will occur every 5 seconds. The code associated with this event should be as follows:

If Condition = True Then
'Code to set the "enabled" property of the timer to False
'Code you need to execute when Shelled program ends
End If

The "trick" with this approach is to figure out what condition to test for (Condition = True, above). In my projects, I also wrote the Shelled program so I coded the Shelled program to create a file named "c:\mark.txt" just before terminating. That done, the condition I test for in the timer is for the existence of "c:\mark.txt" (you probably want to Kill this file in step 3 so it's not already there from last time). If you don't have this kind of control over the Shelled program, you must figure out some other condition that will not occur until the other program is finished and test for that (e.g., change in the date/time attributes of an output file).

Once you get it set up, it works pretty well. For example, if the Shelled program runs for 12 seconds, the timer will execute twice and do nothing because the required condition will still be false. On the third execution (after 15 seconds), the condition will be true and the code associated with the timer will run.

Hope this helps.

Roger
 
Naftali,
You will have to use Windows API calls

1)CreateProcess Lib "Kernel32" Alias "CreateProcessA"
2)WaitForSingleObject Lib "Kernel32"
3)CloseHandle

in order to spawn a child process and wait for it to be closed. I can help you with the code but it is preety exhaustive.

If you want it, I can post it out here. But it works great for me.

Thanks

 

Look in the FAQ area of this forum (I believe it is 5e) Tarek
 
Antzz is correct, you have to use API calls. Here is all the code you need. I picked this up from a VB book a long time ago.

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
Just paste this into a standard module in your project and make calls to SyncShell instead of the VB shell function.
HTH 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.
 
Thanks Ruairi.

Is there a way that I can get also the exit code of the other process?

Naftali
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top