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.
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.
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 OnThreadException(ByVal sender As Object, _
ByVal e As ThreadExceptionEventArgs)
' This is where you handle the exception
' For Instance:
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()
'Hook the ThreadException event to the OnThreadException method.
AddHandler Application.ThreadException, AddressOf OnThreadException
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call
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
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.
VSWIZARD 6.0
Wizard=VsWizard.VsWizardEngine.7.1
Param="WIZARD_NAME = SafeForm"
Param="WIZARD_UI = FALSE"
Param="PROJECT_TYPE = VBPROJ"
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
#Region " Imported NameSpaces "
Imports System
Imports System.Threading
#End Region
''' -----------------------------------------------------------
''' Project : ExceptionHandling
''' Class : SafeForm
'''
''' -----------------------------------------------------------
''' <summary>
''' The SafeForm class will encapsulate methods
''' to handle unhandled exceptions from forms that
''' inherit from this class.
''' </summary>
''' <remarks>
''' </remarks>
''' <history>
''' [John Saunders] 1/21/2005 Created
''' </history>
''' -----------------------------------------------------------
Public Class [!output SAFE_ITEM_NAME]
Inherits System.Windows.Forms.Form
#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()
'Hook the ThreadException event to the OnThreadException method
AddHandler Application.ThreadException, AddressOf OnThreadException
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
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
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<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)
'Handle any unforeseeable exceptions here.
MessageBox.Show(e.Exception.Message)
End Sub
#End Region
End Class
//
// Copyright (c) Microsoft Corporation 2001-2002. All rights reserved.
//
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 /* OLE_E_PROMPTSAVECANCELLED */ :
return -2147221492;
case -2147024816 /* FILE_ALREADY_EXISTS */ :
case -2147213313 /* VS_E_WIZARDBACKBUTTONPRESS */ :
return -2147213313;
default:
ReportError(e.description);
return -2147213313;
}
}
finally
{
dte.SuppressUI = oldSuppressUIValue;
}
}
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.
| You must Sign In to use this message board. | |||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||