How To: Prevent the application from exiting inmediately after starting
Background
Standard EXE applications written in VB6 can be started either from a Main sub or
a startup form.

Selection of the startup object for an Standard EXE project in VB6.
The use of the Main sub is a very common practice in large applications, because
it allows the execution of initialization logic before the load of the main form
of the application, and allows a separation of this logic from the logic of the
form.
When an application that uses the Main sub as startup object is migrated using the
VBUC, equivalent code is generated in .NET, however, due to differences in the behavior
of VB6 and the .NET Framework the applications behave different. Some manual changes
are required to achieve functional equivalence in this case.
In VB6, all the code in the Main sub is executed and the method ends, but the application
continues to run while a form is displayed. In .NET on the other hand, the application
will exit as soon as the Main method exits, any open form at that point will be
closed automatically.
The following sections describe sample scenarios where this behavior affects the
generated code and what kind of manual changes are required to achieve functional
equivalence.
Basic Scenario
The basic scenario is the invocation of the main form of the application from the
Main sub, this is described here.
VB6 Application
We have a simple application with a Main module which contains the Main sub, and
a main form that is displayed in the Main sub.
VB6 Project for the basic startup object scenario.
This is the code for the Main module:
Public Sub Main()
MainForm.Show
End Sub
VB6 code for the Main module.
As mentioned before, this application will start the execution on the Main sub,
display the main form and exit the main sub, keeping the Main form open. The application
will exit as soon as the Main form is closed.
Migrated Application
The migration tool generates lines that are equivalent to the lines in the original
application, it also generates an EWI
informing the user that the "application will terminate when Sub Main() finishes".
//UPGRADE_WARNING: (1047) Application will terminate when Sub Main() finishes. More Information: http://www.vbtonet.com/ewis/ewi1047.aspx
[STAThread]
public static void Main()
{
MainForm.DefInstance.Show();
}
If we execute this code, the Main Form window will be displayed but the application
will exit as soon as the Main method exits, closing the window inmediately. To fix
this behavior, we have two options:
- Show the form using the ShowDialog() method.
- Use the System.Windows.Form.Application.Run() method to show the form.
For this application, as it is a simple one, we will use the first option, the other
option will be seen in a later example.
Manual changes
The use of the System.Windows.Forms.Form.ShowDialog()
method is straightforward. In the case of our sample application we just need to
replace the call to Show() for a call to ShowDialog and we are good to go.
[STAThread]
public static void Main()
{
MainForm.DefInstance.ShowDialog();
}
This simple change makes the form visible and stops the execution of any code after
the ShowDialog call until the form is closed, achieving this way functional equivalence
for the migrated application.
Disadvantages
The main disadvantage of using ShowDialog() is that this method stops the execution
of the caller method until the form is closed, this means that if the source application
has logic that is executed after the form is displayed, tat logic will be executed
only when the form is closed.
Another limitation is that if for some reason the application consists of more than
one form, if all forms are displayed using the ShowDialog() then they will be displayed
sequentially (the second after the first one is closed and so on).
The following example shows a (slightly) more complex application and a more general
solution for the problem of the application exiting inmediately after it is loaded.
Non-Trivial Main method
Here’s a frequent way of starting applications in VB6, which will not work with
the previous solution of using the ShowDialog() method.
Public Sub Main()
SplashForm.Show
InitializeDatabaseAccess
End Sub
VB6 code for the Main module.
Private Sub Timer1_Timer()
Unload Me
MainForm.Show
End Sub
VB6 code for the SplashForm.
The application has a Splash Form that is displayed when the application starts,
this form has a timer that after a couple of seconds closes the Splash Form and
opens the main form of the application. The application also calls a method called
InitializeDatabaseAccess() after displaying the Splash Form, assuming that the initialization
method has been executed when the Main Form is displayed.
If we use the previous solution, two problems will arise:
- The code in the InitializeDatabaseAccess method will be executed when the Splash
Form exits, which will cause problems if the application assumes this code was executed.
- The main form will be displayed but hidden inmediately because the splash form will
be closed and thus the application will exit.
In this particular case, a solution might be to move the call to InitializeDatabaseAccess
before displaying the Splash Form and moving the call to the ShowDialog of the Main
Form after the same call for the Splash Form. e.g.:
[STAThread]
public static void Main()
{
InitializeDatabaseAccess();
SplashForm.DefInstance.ShowDialog();
MainForm.DefInstance.ShowDialog();
}
Possible solution to achieve functional equivalence.
Although this approach works fine, it requires several manual changes to the code
(even for a small application) and it also has the issue that the initialization
code will be executed before showing the splash screen, which means that the application
might take longer to start.
General solution
The following solution requires the addition of two lines to the application’s Main
method that will provide functional equivalence to any application in a simple way.
[STAThread]
public static void Main()
{
SplashForm.DefInstance.Show();
InitializeDatabaseAccess();
MainForm.DefInstance.FormClosed += (s, e) => { System.Windows.Forms.Application.Exit(); };
System.Windows.Forms.Application.Run();
}
General solution to solve the problem.
The idea of this solution is, that with the call to System.Windows.Forms.Application.Run()
we make the application wait until the System.Windows.Forms.Application.Exit()
method is called, then, the previous line assigns an event handler to the FormClosed
event of the Main Form of the application, and this event handler simply calls the
Application.Exit() which will end the execution of the application.
Note that this solution will work as long as the assumption that once the Main Form
is closed the application should terminate. If there are other active forms when
this main form is closed this solution will cause the application to exit regardless
of these forms. The solution in such case would be to keep track of the open forms
of the application and when the last one is closed, call the Application.Exit
method