Can you Close or Exit an application from within a Sub or what would be the 'best practise' for Exiting when the app has failed a logic test?

My app checks for the existance of various files in a Sub Routine off the Form_Load and writes to a log along the way. In the event that 1 of these files does not exist, I want it to Exit program. But somehow while it does report False on the If File.Exists(Filename) and it does write to my log correctly, it slips past the next statement whether it is a Me.Close() or Application.Exit() and returns to the Sub Form_Load.

What puzzles me (yet may provide some clue) is that I have other If IO.Directory.Exists() and If File.Exists(Filename) statement in the Form_Load that do Me.Close properly.

Can someone explain?

In a related question and perhaps more important as a point of discussion, if I'm doing a series of repetitive tests before I move to my main logic Sub Routines, is the Sub Form_Load the place to do it or is it 'best practise' to do these in other Subs from the Form_Load?

Thanks, appreciate input on this

Recommended Answers

All 8 Replies

When you execute Me.Close() it raises the FormClosing event. In the FormClosing handler you can choose to cancel the close by executing

e.Cancel = True

If you do not then the next event to get raised is FormClosed. The code following Me.Close() never gets executed. You can check this by adding the following:

Private Sub Form1_FormClosed(sender As Object, e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
    MsgBox("FormClosed")
End Sub

Private Sub frmMain_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
    MsgBox("FormClosing")
End Sub

Then somewhere else you can add

Me.Close()
MsgBox("after Me.Close()")

You'll never see the "after" message unless you set e.Cancel = True in FormClosing

Any procedures that are executed in the Form_Load event will continue to execute even if there is an error. Also, you cannot close a form when it is Loading. The Close event will only fire after the Load event is complete.

You can however, use a Shared Sub Main statement that provides the logic of showing a Form, execute a procedure, then closing the Form on error (Try...Catch block).

The Form.Close method does exactly that; it tells the form to close. It does not stop the currently executing code block. The following code will demonstrate this behavior and show you an alternative to achieve your goal of stoping execution. Just step through the code in the debugger to observe how the code execution branches and returns.

Public Class Form1
   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
      CheckFiles()
      Stop 'this line will be reached

   'This will exit the executing code block on return.  
   'Since the main form is closed, the program will terminate.
      If Not CheckFilesV2() Then Exit Sub

      Stop 'this one will not
      MsgBox("hi")
   End Sub

   Private Sub CheckFiles()
      CloseForm()
      Stop 'and here
   End Sub

   Private Function CheckFilesV2() As Boolean
      CloseForm()
      Stop 'and here
      Return False
   End Function

   Private Sub CloseForm()
      Me.Close()
      Stop 'yep you got here
   End Sub
End Class

In the following code, the Debug.WriteLine gets executed with visible results but the "Click" message is never displayed. I find that just a little odd.

    Private Sub Form1_FormClosed(sender As Object, e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
        MsgBox("FormClosed")
    End Sub

    Private Sub frmMain_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        MsgBox("FormClosing")
    End Sub

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        Me.Close()
        Debug.WriteLine("click")
        MsgBox("Click")
    End Sub

VB.NET documentation states that events are not guaranteed to fire. Not only that, but the entire handler for Form Load MUST complete before the Form Close event can be fired. If not, VB.NET will ignore the Form Close call. That is why the form remians open; it is still executing the Handler.

If you use a Shared Sub Main, and place the logic there. Then Open the Form is all goes well and display the results. Or, if you insist on using it in the Form Load event handler, then use the End keyword. It will stop all execution and end the application. Though the garbage collector is not guaranteed to clean up memory. Because of this, you may have a memory stack iussue.

Guys, in my frustration over this and after reading all the responses I figured out that my application was flawed in the beginning. I have no reason to use a WinForm since my app doesn't require any human intervention.

The subject started because I had sent my app into a sub routine off the Form_Load and it didn't do what I expected. After reading this I realized that I was doing too much in the Form_Load that wasn't really relevent to that place in the code. I should have placed much of this code in a Button_Click.

Ultimately it made sense to rebuild this as a Console App and I'm now cleaning that up while adding more error checking.

This does bring up another very relevent question for you guys; what is the preferred 'best practice' to Exit out of a Console App since there is no Me.Close(). I've searched this and didn't find much.

I need an exit routine both when the app has successfully finished as well as when it has found a logic error such as the If File.Exists(Filename).

It seems as though an exit routine isn't needed when all goes well; it reaches the end and exits te app. Is that the way it's done or are there cleanup issues I should be doing?

Thanks for all the input here; this is what a real forum is about.

If you don't want to return an exit code then you can just let it run off the end of the Main sub. If you want to set an exit code I think the process is

System.Environment.ExItCode = 7
System.Environment.Exit

Replace 7 with your exit code of choice.

Jim, it seems that I can use 'End' to exit the application if I need to stop on a logical error like If File.Exists(Filename), otherwise it just finishes its task and closes successfully.

I would think this whole thing would be documented better; it is a rather important task :( I just want to try and use 'best practices' when possible.

Thanks for your help

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.