?
Solved

glom visual studio class/struct browser for printing and/or logging

Posted on 2009-02-12
8
Medium Priority
?
408 Views
Last Modified: 2013-12-14
If you have used Visual Studio, you know it has a rather nice browse capability to browse through data members of classes. What I'd like to do is to call some routine that generates the fully expanded data members and values in text form, and send that output to a log file, for study and or diff with previous runs.

Of course, the solution would be MS only and debug only, but it would be a very quick/easy way to record a big hairy data structure before making code changes that are supposed to change the data strucuture in just a few places (or not at all).

Select-all/copy then paste into another document is close to what I want, but the data structure I'm dealing with is very deep and broad, and I don't want to have to expand each item in the tree view by hand.
0
Comment
Question by:mweber02
  • 5
  • 3
8 Comments
 
LVL 31

Expert Comment

by:Zoppo
ID: 23631984
Hi mweber02,

so if I understand you correctly you want to output every entry of the 'Class View' tree of the solution, right?

Attached you can find code for a macro which I wrote for VisualStudio 2008 - I hope you have VS 2008, I don't know if this would work with previous versions too ...

The macro as I wrote it creates a new output window pane 'MacroOutput' and writes the entries line by line with level depending indention. If you need some different output I guess it shouldn't be a big problem to implement it.

BTW: Even with not too large solutions this macro may need a very long time to run. Further if you want to exclude subitems of some items you can do it - just as a sample I implemented to skip children of items named 'Poco', 'Base Types' and 'Maps'.

Hope that helps,

ZOPPO
    Function GetHierarchyAsString(ByVal items As UIHierarchyItems, ByVal level As Long, ByVal output As EnvDTE.OutputWindowPane)
        Dim item As UIHierarchyItem
        Dim indent As String
        Dim expanded As Boolean
 
        For i = 1 To level
            indent += " "
        Next
 
        Try
            expanded = items.Expanded
            items.Expanded = True
 
            For Each item In items
                If item.Name = "Poco" Or item.Name = "Base Types" Or item.Name = "Maps" Then
                    Continue For
                End If
                output.OutputString(indent + item.Name() + Chr(13))
                GetHierarchyAsString(item.UIHierarchyItems, level + 1, output)
            Next
 
            items.Expanded = expanded
        Catch
        End Try
 
    End Function
 
    Sub OuputClassView()
        Dim tree As UIHierarchy
        Dim output As EnvDTE.OutputWindowPane
        Dim panes As EnvDTE.OutputWindowPanes
        Dim items As UIHierarchyItems
 
        panes = DTE.ToolWindows.OutputWindow.OutputWindowPanes
        Try
            output = panes.Item("MacroOutput")
            output.Clear()
        Catch
            output = DTE.ToolWindows.OutputWindow.OutputWindowPanes.Add("MacroOutput")
        End Try
 
        tree = DTE.ToolWindows.GetToolWindow("Class View")
        items = tree.UIHierarchyItems
 
        GetHierarchyAsString(items, 0, output)
    End Sub

Open in new window

0
 
LVL 31

Expert Comment

by:Zoppo
ID: 23632168
BTW, just for info - I continued improving this macro to make it more generic for multiple use cases, maybe you're interested.

Now there are two macros:

OuputClassView: Writes none-filtered entries from 'Class View' - the filter can be passed as an array of strings
OuputFilesView: Writes entries from 'Solution Explorer', up to now without a filter

ZOPPO

    Function OutputTree(ByVal items As UIHierarchyItems, ByVal level As Long, ByVal output As EnvDTE.OutputWindowPane, ByRef skipItems As String())
        Dim item As UIHierarchyItem
        Dim indent As String
        Dim expanded As Boolean
 
        For i = 1 To level
            indent += " "
        Next
 
        Try
            expanded = items.Expanded
            items.Expanded = True
 
            For Each item In items
                If skipItems Is Nothing Then
                    'do nothing
                ElseIf skipItems.BinarySearch(skipItems, item.Name()) > -1 Then
                    Continue For
                End If
                output.OutputString(indent + item.Name() + Chr(13))
                OutputTree(item.UIHierarchyItems, level + 1, output, skipItems)
            Next
 
            items.Expanded = expanded
        Catch
        End Try
 
    End Function
 
    Sub OutputTree(ByVal tree As UIHierarchy, Optional ByVal skipItems As String() = Nothing)
        Dim output As EnvDTE.OutputWindowPane
        Dim panes As EnvDTE.OutputWindowPanes
        Dim items As UIHierarchyItems
 
        tree.Parent.Activate()
 
        panes = DTE.ToolWindows.OutputWindow.OutputWindowPanes
        Try
            output = panes.Item("MacroOutput")
            output.Clear()
        Catch
            output = DTE.ToolWindows.OutputWindow.OutputWindowPanes.Add("MacroOutput")
        End Try
 
        Try
            items = tree.UIHierarchyItems
        Catch
            Exit Sub
        End Try
 
        OutputTree(items, 0, output, skipItems)
    End Sub
 
    Sub OutputTree(ByVal window As String, Optional ByVal skipItems As String() = Nothing)
        Dim tree As UIHierarchy
 
        Try
            tree = DTE.ToolWindows.GetToolWindow(window)
        Catch
            MsgBox("Error: Can't iterate items in window '" + window + "'!")
            Exit Sub
        End Try
 
        OutputTree(tree, skipItems)
    End Sub
 
    Sub OuputClassView()
        Dim skipItems As String()
        skipItems.Resize(skipItems, 3)
        skipItems(0) = "Poco"
        skipItems(1) = "Base Types"
        skipItems(2) = "Maps"
 
        OutputTree("Class View", skipItems)
    End Sub
 
    Sub OuputFilesView()
        OutputTree(DTE.ToolWindows.SolutionExplorer)
    End Sub

Open in new window

0
 
LVL 31

Expert Comment

by:Zoppo
ID: 23632177
hm - seems the code-snippet window isn't VB-style comment aware :o)
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 

Author Comment

by:mweber02
ID: 23633362
Your solution is interesting!

Sorry to be unclear in my request. What I have is actually a struct that is instantiated locally (within a method) so the class view does not display it. I can see it in a watch window.

Can your solution be adapted to work in a watch window, or pass it the name of the struct, or similar? Perhaps there is a way to view the struct in the class view that I am not aware of. The app I'm dealing with is quite large, so a targeted solution would probably be required. I.e. "show me this particular struct".
0
 
LVL 31

Accepted Solution

by:
Zoppo earned 2000 total points
ID: 23634581
ok, I hope I understood - you want to output the values of an object's instance in a running debugging session in a similar matter as the debugger shows it in the watch window.

I attached a macro which does something like this, please test it. In general this could be improved a lot (there's no error checking, the output for now is just shown in a message box) but it may be a good base to implement a better one.

To use it just start the macro when you're at a point in the call stack where the instance is available - then a dialog pops up which asks you for the name of the value to analyze. After that (if no error occured) a message box should pop up showing the result.

Please excuse if maybe it doesn't work in any case - I never did such thing before. But  at least I found out how to differ between pointer and none-pointer members and for some test-structs I tried it works ok.

Unfortunateley I have to leave office now and won't be online over weekend, so the next help I can offer you is on monday morning (German time).

Have a nice weekend,

regards,

ZOPPO
    Function RecurseDebugExpression(ByVal name As String, Optional ByVal nIndent As Integer = 0) As String
        Dim expr As Expression
        expr = DTE.Debugger.GetExpression(name, True)
 
        Dim value, result, indent As String
        Dim i As Integer
 
        For i = 1 To nIndent
            result += " "
        Next
 
        For i = 1 To expr.DataMembers.Count
            If expr.DataMembers().Item(i).Value().Substring(0, 1) = "{" Then
                If (expr.DataMembers().Item(i).Name().Substring(0, 1) = "[") Then
                    'treat pointer in a different way'
                    i += 1
                    result += RecurseDebugExpression("(*" + name + ")." + expr.DataMembers().Item(i).Name(), nIndent + 1)
                Else
                    result += RecurseDebugExpression(name + "." + expr.DataMembers().Item(i).Name(), nIndent + 1)
                End If
            Else
                result += name + "." + expr.DataMembers().Item(i).Name() + " : " + expr.DataMembers().Item(i).Value() + Chr(13)
            End If
        Next
        RecurseDebugExpression = result
    End Function
 
    Sub ShowCurrentStructFromWatch()
        Dim expr As Expression
        Dim str As String = InputBox("Enter value's name")
 
        If str <> "" Then
            str = RecurseDebugExpression(str)
        End If
        MsgBox(str)
    End Sub

Open in new window

0
 

Author Comment

by:mweber02
ID: 23634627
Thanks for your help.
I won't get to testing this right away, but that's not your fault.
I'll accept and give you full points.
0
 

Author Closing Comment

by:mweber02
ID: 31546382
I haven't tested, but it's a good direction for what I'm looking for.
0
 
LVL 31

Expert Comment

by:Zoppo
ID: 23634753
Hi again,

hm - ok, thanks - please feel free to ask me here if you have problems.

I already found one - it doesn't work fine for the expression 'this' or '*this' - if you want to use this use '(*this)' instead.

bye,

ZOPPO
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

zlib is a free compression library (a DLL) on which the popular gzip utility is built.  In this article, we'll see how to use the zlib functions to compress and decompress data in memory; that is, without needing to use a temporary file.  We'll be c…
Programmer's Notepad is, one of the best free text editing tools available, simply because the developers appear to have second-guessed every weird problem or issue a programmer is likely to run into. One of these problems is selecting and deleti…
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
The viewer will learn how to use NetBeans IDE 8.0 for Windows to connect to a MySQL database. Open Services Panel: Create a new connection using New Connection Wizard: Create a test database called eetutorial: Create a new test tabel called ee…

621 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question