Introduction
This article hopes to simplify two key hurdles that took me a while to get past. First, unhandled exceptions. While I'm sure that none of you ever have any of these, I seem to get them at the most inopportune times. The unfriendly Continue or Quit dialog just does wonders for your reputation and almost inevitably means a crash will be imminent while you're presenting your application, or, even worse, after releasing it. The second piece that I'd like to show you is how to simplify creating templates to work from. Inheritance could be one of the best things to ever happen to Visual Basic, so, by all means, take advantage of it.
Background
I have to mention that what led me to putting this together was a very nice component by Stratalogic Software, called SLS Exception Reporter. It's a nice way of managing any exception and works great in conjunction with this template.
Part I: Unhandled Exceptions
Even though we always hope to have everything encapsulated within nice structured Try
-Catch
-Finally
blocks, occasionally, an error happens for no foreseeable reason. When working with Windows Forms, this raises a System.Threading.ThreadException
event. There's very little that you have to actually do to handle this event.
First, create a method called OnThreadException
:
Private Sub </FONT>OnThreadException(ByVal sender As Object, _
ByVal e As ThreadExceptionEventArgs)
MessageBox.Show(e.Exception.Message)
End Sub
This next part is to wire up the OnThreadException
handler to the Application.ThreadException
event. This should be done in the constructor of the form, before the InitializeComponent
method.
Public Sub New()
MyBase.New()
AddHandler Application.ThreadException, AddressOf OnThreadException
InitializeComponent()
End Sub
Now, you can choose to handle the exception in any way that you wish and be sure that the user doesn't end up with the Continue or Quit dialog. If you happen to use the Stratalogic component, you may do something like:
Private oExceptionReporter As SLSExceptionReporter
Private Sub OnThreadException(ByVal sender As Object, _
ByVal e As ThreadExceptionEventArgs)
oExceptionReporter = New SLSExceptionReporter.ExceptionReporter
oExceptionReporter.ContactEmail = "myemail@mydomain.com"
oExceptionReporter.DisplayException(e.Exception)
End Sub
Part II: Safe Form Template
Now, let's inherit all of our forms from this one, right? Now I'm a bit lazy.. err.. efficient I mean, so I want to do this the easiest possible way. I won't go into the finer points of creating templates; instead, I'll give you one to start from. I did this using Visual Studio .NET 2003. I'm not sure what the differences would be for other versions, but if you're using 2003, browse to C:\Program Files\Microsoft Visual Studio .NET 2003\Vb7.
- Open VBProjectItems and create a file called SafeForm.vsz to configure your form wizard:
VSWIZARD 6.0
Wizard=VsWizard.VsWizardEngine.7.1
Param="WIZARD_NAME = SafeForm"
Param="WIZARD_UI = FALSE"
Param="PROJECT_TYPE = VBPROJ"
- Next, you'll need a .vsdir file in each of the areas that you would like to have the wizard accessible from.
In the Local Project Items and UI folders, create a file called SafeForm.vsdir. In this file, type:
..\SafeForm.vsz|SafeForm|#3050|10|#3051|
{164B10B9-B200-11D0-8C61-00A0C91E29D5}|4527| |Form.vb
- Now, go back up to C:\Program Files\Microsoft Visual Studio .NET 2003\Vb7\VBWizards.
- Create a folder called SafeForm and two folders inside that called Scripts and Templates.
- There should be a folder called 1033 under each of these two directories.
- Under Templates\1033, create a file called Form.vb and paste the following code:
#Region " Imported NameSpaces "
mports System
Imports System.Threading
#End Region
Public Class [!output SAFE_ITEM_NAME]
Inherits System.Windows.Forms.Form
#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()
AddHandler Application.ThreadException, AddressOf OnThreadException
InitializeComponent()
End Sub
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
Private components As System.ComponentModel.IContainer
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
components = New System.ComponentModel.Container()
Me.Text = "[!output SAFE_ITEM_NAME]"
End Sub
#End Region
#Region " Internal Methods "
Private Sub OnThreadException(ByVal sender As Object, _
ByVal e As ThreadExceptionEventArgs)
MessageBox.Show(e.Exception.Message)
End Sub
#End Region
End Class
- You will need a file called default.js in the Scripts\1033 folder:
function OnFinish(selProj, selObj)
{
var oldSuppressUIValue = true;
try
{
oldSuppressUIValue = dte.SuppressUI;
var bSilent = wizard.FindSymbol("SILENT_WIZARD");
dte.SuppressUI = bSilent;
var strItemName = wizard.FindSymbol("ITEM_NAME");
var strTemplatePath = wizard.FindSymbol("TEMPLATES_PATH");
var strTemplateFile = strTemplatePath + "\\Form.vb";
var VSProject = selProj.Object;
var refs = VSProject.References;
var ref;
ref = refs.Add("System");
ref = refs.Add("System.Data");
ref = refs.Add("System.Drawing");
ref = refs.Add("System.Windows.Forms");
var item = AddFileToVSProject(strItemName, selProj,
selObj, strTemplateFile, true);
if( item )
{
item.Properties("SubType").Value = "Form";
var editor = item.Open(vsViewKindPrimary);
editor.Visible = true;
}
return 0;
}
catch(e)
{
switch(e.number)
{
case -2147221492 :
return -2147221492;
case -2147024816 :
case -2147213313 :
return -2147213313;
default:
ReportError(e.description);
return -2147213313;
}
}
finally
{
dte.SuppressUI = oldSuppressUIValue;
}
}
- Now, start Visual Studio and create a Visual Basic .NET Windows Application.
- Right-click Add New Item... and you should see a new choice called "Safe Form".
- After adding the Safe Form to your project, make sure that all other forms inherit from
SafeForm
and not System.Windows.Forms.Form
.
Now, all unhandled exceptions are managed each time you create a new Windows Forms project, since you will have the SafeForm template there to inherit from. You can also include any other code in your template to make starting a new project easier.
Enjoy.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.