Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Highlight VS.NET code position from exception while debugging

0.00/5 (No votes)
14 Apr 2004 1  
This snippets provide a way to extract line number information from an exception's stack trace and highlighting the line in source code when the debugger is attached. I copied it out from a large project and it won't therefore be usable 'as is', but the essentials could easily be reused.

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
        'displays a single error; if the cascade is defined 

        'it will be displayed except its last entry

        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
            'visualize the stack trace if necessary

            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
              'secondly attach the entry points extracted from 

              'the exception stack trace string

              'as they stand in errx.details (which, in fact, 

              'contains the result of exception.tostring)

              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
               'ignore this

             End Try
               .lstStack.Visible = CBool(.lstStack.Items.Count > 0)
            End If
            'display and wait for the user to react

            .DoLayout(errX)
            .ShowDialog()
            'if there was a validation, then try to focus the control

            Try
                errX.ValidatedControl.Focus()
            Catch ex As Exception
                'ignore this

            End Try
            'clear the collection now

            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
        'dive into the code

        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
            'can't do anything about that, dead end

            Beep()
        End Try
    End Sub

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here