Intention
In our commercial apps, there's a specially designed Windows Forms dialog in use to display runtime error messages (like 'file not found' and the like) to the user. However, when debugging, this dialog shows up like it would in the release version, but is enhanced with a list of the exceptions that occurred. Each exception can be clicked on, and on doing so, the corresponding source code position will immediately be found and highlighted in the IDE on behalf of the file name and line number information contained in the exception's message text and stack trace details. This proved extremely useful. The essentials are shown below.
Object containing the exception information:
Public Class cdoErrStackframe
Public Filename As String
Public LineNumber As Integer
Public ColumnNumber As Integer
Public FunctionName As String
Public Sub New(ByVal frX As StackFrame)
With frX
Filename = .GetFileName
LineNumber = .GetFileLineNumber
ColumnNumber = .GetFileColumnNumber
FunctionName = .GetMethod.Name
End With
End Sub
Public Sub New(ByVal sFilename As String, ByVal sFunctionName_
As String, ByVal iLinenumber As Integer)
Filename = sFilename
LineNumber = iLinenumber
ColumnNumber = 1
FunctionName = sFunctionName
End Sub
Public Overrides Function ToString() As String
Dim fName As String
fName = Mid(Filename, Filename.LastIndexOf("\") + 2)
fName = Left(fName, fName.LastIndexOf("."))
Return fName & "::" & FunctionName & "() -- " & LineNumber
End Function
End Class
This snippet shows a way to extract the necessary information from the exception to a string output. It is sure to be version-dependant, but works fine ;-)
Friend Function VisualizeError(ByVal errX As cdoError,_
ByVal Cascade As cdoErrors) As cdoSrv.cdoErrorResults
Dim frmX As New frmMsg
Dim errC As cdoError
With frmX
.Text = errX.Title
.lblMsg.Text = errX.Msg
.lblExplanation.Text = errX.Details
.lblRemedy.Text = errX.Remedy
If Not (Cascade Is Nothing) Then
For I As Integer = 0 To Cascade.ErrorList.Count - 2
errC = Cascade.ErrorList.Item(I)
.lstCascade.Items.Add(errC)
Next
End If
If errX.fromException And Debugger.IsAttached Then
Try
Dim sf As New System.Diagnostics.StackTrace(True)
For J As Integer = 0 To sf.FrameCount - 1
If Not (sf.GetFrame(J).GetFileName Is Nothing) Then
If sf.GetFrame(J).GetFileName.IndexOf("cdoErrors.vb") <= 0 Then
.lstStack.Items.Add(New cdoErrStackframe(sf.GetFrame(J)))
End If
End If
Next
Dim sX As String = errX.Details
Dim sY(0) As String
Dim sFilename As String, sFunction As String, iLine As Integer
For I As Integer = 0 To Len(sX) - 1
If sX.Substring(i).StartsWith(" at") Then
ReDim Preserve sY(UBound(sY) + 1)
sY(UBound(sY)) = sX.Substring(I + Len(" at"))
If sY(UBound(sY)).IndexOf(vbLf) > 0 Then
sY(UBound(sY)) = Trim(Left(sY(UBound(sY)),_
sY(UBound(sY)).IndexOf(vbLf) - 1))
Else sY(UBound(sY)) = Trim(sY(UBound(sY)))
End If
Next
For I As Integer = UBound(sY) To 1 Step -1
If sY(i).IndexOf("vb:line") > 0 Then
sFunction = sY(I).Substring(0, sY(i).IndexOf("("))
If sFunction.IndexOf(".") > 0 Then
sFunction = sFunction.Substring(sFunction.LastIndexOf(".") + 1)
sFilename = sY(i).Substring(sY(i).IndexOf(" in ") + Len(" in "))
If sFilename.IndexOf(":line") > 0 Then
sFilename = sFilename.Substring(0, sFilename.LastIndexOf(":"))
iLine = CInt(sY(i).Substring(sY(i).LastIndexOf(":line ")_
+ Len(":line ")))
.lstStack.Items.Add(New _
cdoErrStackframe(sFilename, sFunction, iLine))
End If
Next
Catch ex As Exception
End Try
.lstStack.Visible = CBool(.lstStack.Items.Count > 0)
End If
.DoLayout(errX)
.ShowDialog()
Try
errX.ValidatedControl.Focus()
Catch ex As Exception
End Try
Clear()
Return .Result
End With
End Function
Navigation essentials (shows how to get the IDE to open a file and highlight a certain line in source code):
Private Sub lstStack_DoubleClick(ByVal sender_
As Object, ByVal e As System.EventArgs) Handles lstStack.DoubleClick
If lstStack.SelectedItem Is Nothing Then Return
Try
If Not Debugger.IsAttached Then Return
With CType(lstStack.SelectedItem, cdoErrStackframe)
Dim DTE As EnvDTE.DTE
DTE = _
System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE")
Dim itmX As EnvDTE.ProjectItem = _
DTE.Solution.FindProjectItem(.Filename)
itmX.Open(EnvDTE.Constants.vsViewKindCode).Activate()
Dim objSel As EnvDTE.TextSelection_
= DTE.ActiveDocument.Selection
objSel.StartOfDocument()
objSel.MoveToLineAndOffset(.LineNumber,_
.ColumnNumber)
objSel.SelectLine()
End With
Catch ex As Exception
Beep()
End Try
End Sub