Ask Kathleen
Enable the Application Framework in VB
Learn what enabling the application framework in VB actually does and what an invariant culture is and how you take advantage of it.
Q What happens when I check "Enable application framework" in my Visual Basic application? Why does my Sub Main disappear from the Startup Object dropdown, what happens with the different shutdown modes, and what is a single instance application?
A Visual Basic supports an "Application Framework" that makes it easier to manage the startup, shutdown, and exception management of an application. You enable or disable the application framework with a check box in the Project Properties. The application framework is part of the work Visual Basic does to make your development easier.
Whether or not you use the Application Framework, Visual Basic generates a hidden My.Application class for your application. The base class is ConsoleApplicationBase if you don't have the Application Framework enabled and WindowsFormsApplicatonBase if you do have it enabled. Both of these classes are in the Microsoft.VisualBasic namespace. You can see part of the generated code if you select Show All Files using the button at the top of Solution Manager under My Project, where you'll find Application.MyApp and, under that, Applicaton.Designer.vb. Application.MyApp is an XML description of your application used in generating Application.Designer.vb and for the Project window.
The part of the My.Application class that you can't see includes a shared Sub Main as the entry point of the application. This calls the constructor in the visible generated (designer) class. The hidden partial class contains code that never changes, and the designer generated partial class sets values specific to your selections in the project window. The reason Sub Main disappears from the startup combo box is that Visual Basic is supplying Sub Main for you.
The WindowsFormsApplicationBase class does most of the heavy lifting. You could code some of the features yourself. For example, you can enable visual styles with this code:
Application.EnableVisualStyles()
Single instance applications, splash screens, and varying shutdown modes are more difficult to code yourself. In addition to displaying the splash screen, Visual Basic ensures it stays open long enough that it's more than an annoying flash and even lets you control how long it's open.
A single instance application doesn't allow more than one instance of the application to run at the same time. Rather than starting another instance, the existing instance gets focus when the user tries to execute the application a second time. If you request a single instance application, Visual Basic looks first for another running copy of the application and switches to it, if possible. The code for this is not for the faint of heart, and it's great to get this behavior by just checking a box.
Partly for legacy reasons, Visual Basic supplies an alternate shutdown mode. In somewhat simplified terms, Windows manages the message queue for events based on a window, or form. When this main form closes, the application has no message queue and closes. Prior to .NET, Visual Basic used an invisible form for the message queue, and thus you could open and close visible forms at will. In .NET, the message queue is associated with the main displayed form of the application and applications normally shut down when the first form closes, regardless of whether other forms are open.
There are two ways to startup the main form of a WinForms application. You can pass an instance of the form to Application.Run, or you can pass an application context. Passing an instance of a form is common when using a Sub Main as an entry point to the application. When you pass a form, .NET uses the default application context to manage information about the application thread. If you pass an application context, .NET uses the one you specify. You can create a custom context derived from ApplicatonContext that manages forms in response to the OnMainFormClosed event, but of course, it's easier to let Visual Basic do all this work for you, with the option of closing the application when the main form closes or the last form closes.
I explored this because I dislike the smoke and mirrors feeling Visual Basic can sometimes give. But once I understood how it worked, I rather liked Visual Basic taking care of these things. Realizing these are just classes doing ordinary but sometimes complex things opens the door to using them in C#. If you need a single instance application or you need to keep your application running when all forms are closed, you can just inherit from these Visual Basic classes in your C# applications.
You might wonder how I figured this out. You can find out more about what's going on in the framework using any decompilation tool, including ILDASM that's part of the Visual Studio install. However, ILDASM requires you read and understand IL. A decompilation tool such as Lutz Roeder's .NET Reflector expresses the code of an assembly in VB or C# code. You can determine what's in the hidden generated partial class by seeing what's in the final class (using Reflector) and knowing what's in the visual partial class. You can also see how the WindowsFormsApplicationBase implements a task like keeping the application open when the main form shuts down.
When I understand what Visual Basic is doing for me, I'm generally comfortable with it and happy to have Visual Basic doing the hard work. I'm often jealous of these capabilities when I'm working in C#, and happy to encounter those occasions where I can leverage the work of the VB team, even in my C# work.
Q What's an invariant culture and should I use it?
A The invariant culture provides a single culture that guarantees consistent results in comparisons. It is one of three culture types provided in.NET's globalization system; the others are language based cultures and locale based cultures. Locale based cultures allow features such as numeric and date formatting to differ while using the same language. Thus en-US and en-GB use the same language (English), but differ in date and numeric formatting.
The invariant culture happens to be en-US. Thus, if you're writing your application and have your computer set for English in the U.S., you will see no difference when you use the invariant culture. But when some of your users reset their operating system language or locale, your application might behave differently. This is important even if you're not localizing your application because it's not the languages your application supports, but how the user sets his or her operating system. A number of problems can occur, but the two of most important are comparisons used for security decisions or other key decisions and your persistence format.
To control comparisons, use the String.Compare method rather than a simple equals (C# double equals) sign. The String.Compare method has several overloads and either of the following does a case insensitive invariant comparison:
Dim s1 As String = "FILE"
Dim s2 As String = "File"
If String.Compare(s1, s2, _
StringComparison.InvariantCultureIgnoreCase) = 0
Then Console.WriteLine("Matches ordinal")
End If
If String.Compare(s1, s2, _
True, CultureInfo.InvariantCulture) = 0 Then
Console.WriteLine("Matches invariant")
End If
You can't count on other cultures behaving as you anticipate when doing comparisons. For, example, this comparison doesn't match because of the way the Turkish letter "i" works:
Dim culture As Globalization.CultureInfo = _
CultureInfo.GetCultureInfo("tr")
If String.Compare(s1, s2, True, culture) = 0 Then
Console.WriteLine("Matches Turkish")
End If
When the string is part of a security or other key decision point, consider employing a case sensitive comparison using either String.Compare with StringComparison.InvariantCulture or String.CompareOrdinal using the invariant culture for the comparison.
You'll have similar problems when parsing dates or numerics, or formatting them for output or persistence. At each point you display, format, or parse strings in your application, you should consider whether the formatting behavior is for a single user, or will be shared among users with different locals.
About the Author
Kathleen is a consultant, author, trainer and speaker. She’s been a Microsoft MVP for 10 years and is an active member of the INETA Speaker’s Bureau where she receives high marks for her talks. She wrote "Code Generation in Microsoft .NET" (Apress) and often speaks at industry conferences and local user groups around the U.S. Kathleen is the founder and principal of GenDotNet and continues to research code generation and metadata as well as leveraging new technologies springing forth in .NET 3.5. Her passion is helping programmers be smarter in how they develop and consume the range of new technologies, but at the end of the day, she’s a coder writing applications just like you. Reach her at [email protected].