(c) 2003 Visual Studio Magazine 
Fawcette Technical Publications

VB.NET	Specify a Sub Main
Listing 1	WinForms allows you to set a startup form or to specify a Sub Main. Specifying a Sub Main lets you define a global exception handler that frees you from putting Try/Catch blocks within your code, except when you can accomplish something in the Catch or Finally. 

Option Strict On
Option Explicit On 

Imports System
Imports System.Windows.forms

Public Class Startup
	Private Shared frmTest As New Test
	Private Shared mxmlHints As Xml.XmlDocument
	Const vbcrlf As String = _
		Microsoft.VisualBasic.ControlChars.CrLf

	Public Shared Sub main()
		Dim exceptionHandler As New _
			GlobalExceptionHandler
		AddHandler Application.ThreadException, _
			AddressOf _
			exceptionHandler.OnThreadException
		Application.Run(frmTest)
	End Sub

	Private Shared ReadOnly Property xmlHints() _
		As Xml.XmlDocument
		Get
			If mxmlHints Is Nothing Then
				OpenXMLHintFile()
			End If
			Return mxmlHints
		End Get
	End Property

	Public Class GlobalExceptionHandler
		Public Sub OnThreadException( _
			ByVal sender As Object, _
			ByVal t As _
			System.threading. _
			ThreadExceptionEventArgs)
			If _
				System.Configuration. _
				ConfigurationSettings. _
				AppSettings.Get( _
				"DisplayExceptions") = _
				"Developer" Then
				Try
					Dim frm As New ExceptionDisplay
					If frm.Show(t.Exception, _
						Startup.frmTest. _
						ActiveControl, _
						Startup.xmlHints) = _
						DialogResult.Abort Then
							frmTest.Close()
					End If
				Catch exLocal As System.Exception
					Try
						MessageBox.Show( _
							"Fatal Error" & vbcrlf & _
							vbcrlf & _
							t.Exception. _
							GetBaseException. _
							ToString,"Fatal Error", _
							MessageBoxButtons. _
							AbortRetryIgnore, _
							MessageBoxIcon.Stop)
					Finally
						Application.Exit()
					End Try
				End Try
			Else
				MessageBox.Show( _
					"User Friendly Message")
			End If

		End Sub

	End Class


VB.NET	Display Individual Exceptions
Listing 2	The specialized WinForms exception display shows nested exceptions in a treeview, so the treeview's AfterSelect event displays the individual exceptions. This event parses the stack tray into a filtered and unfiltered strongly typed collection of the StackEntry object. 

Private Sub tvExc_AfterSelect(ByVal sender As _
	System.Object, ByVal e As _
	System.Windows.Forms.TreeViewEventArgs) _
	Handles tvExc.AfterSelect
	Dim ex As System.Exception
	Dim tnode As Windows.Forms.TreeNode
	Dim ar As New System.Collections.ArrayList
	Dim arShort As New _
		System.Collections.ArrayList
	Dim entry As StackEntry
	Try
		tnode = tvExc.SelectedNode
		If Not tnode Is Nothing Then
			If TypeOf tnode.Tag Is _
				System.Exception Then
				ex = CType(tnode.Tag, _
					System.Exception)
			End If
		End If
		If Not ex Is Nothing Then
			txtMessage.Text = ex.Message
			txtStack.Text = ex.StackTrace
			Dim stack As String() = _
				ex.StackTrace.Split( _
				Microsoft.VisualBasic. _
				ControlChars.Cr)
			For i As Int32 = 0 To _
				stack.GetUpperBound(0)
				entry = New StackEntry(stack(i), i)
				ar.Add(entry)
				If Not entry.IsFramework Then
					arShort.Add(entry)
				End If
			Next
		End If
		mStackArray = _
			CType(ar.ToArray(GetType(StackEntry)), _
			StackEntry())
		mStackArrayShort = _
			CType(arShort.ToArray( _
			GetType(StackEntry)), StackEntry())
		gridStack.SetDataBinding( _
			mStackArrayShort, "")
	Catch exception As System.Exception
		Diagnostics.Debug.WriteLine(exception)
	End Try
End Sub

