I have a console program calling a series of other console programs (they are all Xojo).
I thought I would try a loop to check for when the shell was finished, but that doesn’t seem to be doing it and each command gets executed one after another without any pause and changing the mode doesn’t make any difference that I can tell.
Ideally I would like them all running and then go back to the top of the loop and run again. But I am OK with them running serially.
Any thoughts on how to do this?
For i = 0 to arrToDo.Ubound
Do Until DoneFlag = "YES"
If ExtractFolder.Exists then
DeleteTargetDir()
Else
DoneFlag = "YES"
End If
Loop
sh.Mode = 0
sh.Execute("E:\\bin\\mcunzip\\mcunzip.exe -s E:\\110901\\exported_data\" + arrToDo(i) + " -t E:\\folder1\\folder2\\extracts")
sh.Execute("E:\\bin\\mcbounces\\mcbounces.exe -m " + PgmMode)
sh.Execute("E:\\bin\\mcclicks\\mcclicks.exe -m " + PgmMode)
sh.Execute("E:\\bin\\mccomplaints\\mccomplaints.exe -m " + PgmMode)
sh.Execute("E:\\bin\\mclistmembership\\listmembership.exe -m " + PgmMode)
DoneFlag = "NO"
ShellRunning = "YES"
Do Until ShellRunning = "NO"
If sh.IsRunning then
ShellRunning = "YES"
Else
ShellRunning = "NO"
End If
Loop
Next i
First, on Windows, I believe you have to be aware of the Timeout property. It may be that your shell is exiting prematurely.
Second, you aren’t checking for an error, so perhaps your shell isn’t doing what you think it is?
Third, with mode = 0, the shell will execute its command before returning control to your app. By definition, it’s “done” when your program reaches the next line of code so you have no need for the whole “ShellRunning” apparatus.
If you want them running in parallel, create a shell object for each command, add them to an array, set their modes to 1, Execute, and then check each one until they are all done. Be sure to call either sh.Poll on each or App.DoEvents in the loop to give them time to finish and update their status.
Alternatively, you can create a Shell subclass that re-runs itself when complete, but that’s probably a topic for another day.
As Kem mentioned, be sure to set the sh.Timeout value to -1 or Windows will kill your task if it takes longer than 2 seconds.
Make DoneFlag a Boolean and try you code this way:
For i = 0 to arrToDo.Ubound
Do Until DoneFlag
If ExtractFolder.Exists then
DeleteTargetDir()
Else
DoneFlag = True
End If
Loop
sh.Mode = 1
sh.TimeOut = -1
sh.Execute("E:\\bin\\mcunzip\\mcunzip.exe -s E:\\110901\\exported_data\" + arrToDo(i) + " -t E:\\folder1\\folder2\\extracts")
Do
sh.Poll
App.DoEvents(2)
Loop Until Not sh.IsRunning
If sh.ErrorCode <> 0 Then
// Handle error or build error stack
End If
sh.Execute("E:\\bin\\mcbounces\\mcbounces.exe -m " + PgmMode)
Do
sh.Poll
App.DoEvents(2)
Loop Until Not sh.IsRunning
If sh.ErrorCode <> 0 Then
// Handle error or add to error stack
End If
sh.Execute("E:\\bin\\mcclicks\\mcclicks.exe -m " + PgmMode)
Do
sh.Poll
App.DoEvents(2)
Loop Until Not sh.IsRunning
If sh.ErrorCode <> 0 Then
// Handle error or add to error stack
End If
sh.Execute("E:\\bin\\mccomplaints\\mccomplaints.exe -m " + PgmMode)
Do
sh.Poll
App.DoEvents(2)
Loop Until Not sh.IsRunning
If sh.ErrorCode <> 0 Then
// Handle error or add to error stack
End If
sh.Execute("E:\\bin\\mclistmembership\\listmembership.exe -m " + PgmMode)
Do
sh.Poll
App.DoEvents(2)
Loop Until Not sh.IsRunning
If sh.ErrorCode <> 0 Then
// Handle error or add to error stack
End If
// if you created an error stack, handle the error events here
DoneFlag = False
Next i
Because mode 0 blocks and causes the console app to zoom in CPU utilization unnecessarily.
Also, note that the Windows timer minimum is 14-15ms, but using 2 seems to force the loop to stay very tight on recognizing the completion of the shell process.
What about starting each Shell, adding it to an array, then looping through the array to remove the ones that are done? When the array is empty, they are all done and we can move on. This would have the advantage of using multiple processors.
Kem was right that the problem I was having was that the shell was timing out.
And then there were all the other answers and the discussion.
Thanks @Tim Jones for the code and the explanations.