Pause a program without sleeping

jimmygoska

Member
Joined
Apr 12, 2010
Messages
5
Programming Experience
Beginner
Hey,

I'm pretty new to VB and have had a lot of trouble with this program i'm writing. The problem that I'm encountering right now is that I can't seem to get my program to wait for a couple seconds for another application to load before it starts to check if it's open. Here's what I've got (feel free to tell me its a terrible way of writing!):

VB.NET:
Private Sub Running_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown
        Main.Enabled = False
        ProgressBar1.Style = ProgressBarStyle.Marquee

        Dim path As String = System.Environment.CurrentDirectory
        Dim yes As String = "cmd /K CD " & path & "\OASIC & oasicer hammer_8_8.txt"
        Dim fullpath As String = path & "\OASIC\oasicer.exe"

        Shell(yes, AppWinStyle.NormalFocus)


        System.Threading.Thread.Sleep(500)    <--------- This is the problem


        Dim ProgramRunning As Boolean = True
        While ProgramRunning = True
            If ProcessesRunning("oasicer") = 1 Then
                ProgramRunning = True
            ElseIf ProcessesRunning("oasicer") = 0 Then
                ProgramRunning = False
                MessageBox.Show("It's closed!", "Done", MessageBoxButtons.OK) ' = Windows.Forms.DialogResult.OK Then Me.Dispose()
            End If
        End While
    End Sub

ProcessesRunning is a function that just checks the existance of a process called "oasicer".

So if I don't have the sleep function then oasicer hasn't loaded and it says it's finished straight away, but if I call a 5s sleep then it crashes, and not for just 5 sec. Is there a replacement for this line? Something that would just delay going to the while loop?

Any help is greatly appreciated!
Thank you for your time!
 
Use Process Class (System.Diagnostics) instead of Shell function. As for "waiting" you can either listen for the Exited event of the process, or start it in a secondary thread and where you call WaitForExit method.
 
Hi John,

Thanks for your reply.
Of the many problems I had one of them was to use System.Diagnostics. No matter what I tried I couldn't get the syntax right. Could you maybe elaborate how to do this using the code above? The program oasicer is normaly run by opening a console, changing the directory to the location of oasicer and typing
VB.NET:
 oasicer hammer_8_8.txt
I tried using
VB.NET:
Dim oasicer As Process
oasicer.StartInfo.FileName = path & "\OASIC\oasicer.exe"
oasicer.StartInfo.Arguments = "hammer_8_8.txt"
oasicer.Start()
but this left my computer frozen.

Also, how do you listen for the exited event of the process?

Thanks again for helping!
 
You probably need to set the WorkingDirectory of the ProcessStartInfo to the folder containing the program you want to run. Many programs assume that their working directory is the same folder as their EXE is in.
 
Also, how do you listen for the exited event of the process?
You can use a WithEvents variable and as usual select the Exited event in the dropdown, or dynamically attach with AddHandler statement. If you only have one process instance (or you will only allow one simultaneous process) the WithEvents approach is the easier option. There is a code sample in help topic for Exited event. In the main help topic I linked to you can follow "Process Events" and click the Exited event to see that help topic.
 
Thank you both a lot for your help! So far everything seems to be working! In your last post John, was there meant to be a link?
Thanks!
 
I read through that and tried to get one of the forms to close when the process finishes but when I type

VB.NET:
Friend Sub ProcessExited(ByVal sender As Object, ByVal e As System.EventArgs)
    Me.Hide()
End Sub
I get an error message about cross-threading, which I looked up but I don't understand the .InvokeRequired method. Can you shed some light please?
Thanks again!
 
There is no InvokeRequired method. InvokeRequired is a property and Invoke is a method.

Generally speaking, you can only access members of controls on the thread that created them, i.e. your main UI thread. If your event is raised on a secondary thread, in which case your event handler is executed on a secondary thread, then you can't access control members directly.

You test the InvokeRequired property basically to work out whether you're on the UI thread or not. True means that you are nor on the UI thread and you must invoke a delegate on the UI thread in order to access the control. False means that you are on the UI thread and can access the control directly. You call the Invoke method to pass a delegate across the thread boundary to the UI thread and call the specified method. For detailed instructions read this.
 
Set Process.SynchronizingObject Property (System.Diagnostics) to the form instance (Me) and the event is raised in UI thread.

Aha! Didn't realise that Process had that property. Definitely the easier option.

If the Process class is like the Timer and FileSystemWatcher classes, adding an instance to your form in the designer instead of doing it yourself in code will set the property to the form by default. If you will only ever maintain a single reference to a Process object then I'd go that route.
 
Back
Top