RSS

A fix to the awesome WPF Snoop utility.

Tue, Jul 21, 2009

Staff Posts, Tips and Tricks

SelfAnyone developing on the WPF platform surely knows the Snoop utility by Pete Blois. It is absolutely awesome and I cannot imagine developing WPF applications without it.

However, there is a problem with it. One cannot snoop WPF framework elements nested too deep. By too deep I mean somewhere around 60 layers. Trying to snoop at that nesting level crashes the Snoop and since it is injected into the snooped application process space, the application being snooped is crashed as well.  Which is very annoying.

First of all, there is nothing wrong with Snoop. The problem is inherent in WPF – one just cannot nest too many WPF framework elements. The limit is not 60, of course. It is 255 and is very easy to check. Try to write a simple WPF application with 256 nested panels – it is impossible. At some point the application will crash. Debugging it reveals an exception with the following message:

Layout recursion reached allowed limit to avoid stack overflow: ’255′. Either the tree contains a loop or is too deep.

This msdn forum post is precisely about this issue. Note, that a reply from a Microsoft guy Rob Relyea promises to increase the limit from 255 to 4096 in the upcoming .NET 3.5 “servicing release”. But, until then the problem exists.

So, why is Snoop affected at all? Simple, Snoop uses the WPF TreeView control to display the hierarchy of snooped WPF framework elements. The depth of a node in that tree is directly proportional to the nesting level of the respective snooped element. The following image is a snapshot of that tree created using the Snoop itself:

A snapshot of the Snoop property tree view.

A snapshot of the Snoop property tree view.

(Actually, this is a slightly different version of the original Snoop. I have added the nesting level in the square brackets to the display of a node)

Inspecting the tree gives us the following formula for the nesting depth of a TreeViewItem object – 8 + 4*n, where n is the nesting depth of the respective snooped element. Hence snooping at the first framework element in a WPF application produces a node nested 12 levels deep, whereas snooping at an element at level 60 corresponds to a TreeViewItem at level 248 – dangerously close to the hard coded WPF nesting limit.

In reality, deep snooping of a complex WPF application almost always hits this limit, bringing down the Snoop code along with the snooped application.

So, how can one deal with this unfortunate situation? I see these ways:

  • Be careful not to snoop too deeply – never works.
  • Use the filter textbox to change the root node of the element TreeView. This is a good workaround, but from my own experience it is easy to forget oneself and snoop carelessly too deep – bang, you are toast.
  • Forget about snooping, until the .NET 3.5 “servicing release” is actually released. The reply promising this release dates back to April 17th 2008. I have checked the state of the matters today (July 21st 2009) – the limit is still 255.
  • Fix somehow the Snoop TreeView.

Since I love Snoop very much and use it extensively, I have chosen to fix this issue once and for all. The following items depict the fix:

  • When a new node is added to the TreeView calculate its expected nesting level using this formula – rootLayoutDepth + levelLayoutDepth * n, where
    • rootLayoutDepth is the depth of the first TreeViewItem, calculated automatically somewhere in the beginning.
    • levelLayoutDepth is the depth difference between a node and its child, calculated automatically somewhere in the beginning and is assumed to be constant thereafter.
    • n is the zero based nesting level of the particular snooped element.
  • If the expected nesting level is above 240, then a new TreeView root node is picked. I use the filtering feature of Snoop to setup a special reduce depth filter behind the scenes.

That’s it. There are, of course, many details to it, but the overall picture is captured pretty accurately by these two items.

A few final notes:

  • The Mole visualizer does not have this problem, although it also displays the tree view of inspected elements. The reason is that Mole uses Windows Forms TreeView, which is a single control regardless of how many nodes it displays and how deep they are nested. The nodes are simply drawings on the control’s canvas.
  • The described element nesting limit is not a regression from the Win32 world. Plain old Win32 windows have this limit as well, as described in this post.
  • I have mentioned this issue some time ago in this msdn blog post. Cory Plotts responded to my post and he has added some code to the original Snoop source to better handle interop scenarios. Refer to his blog for details here.
  • In addition to fixing the nesting issue, I have made the following changes to the original Snoop source code:
    • Fixed the property grid view – the last Snoop release has broken it.
    • Added the nesting level in the square brackets to the display of a node in the element tree.
    • Added a test application to the Snoop solution to make sure snooping at deeply nested elements works correctly.
    • Added a few more exception checks.

Last, but not least – the source code. Since I am not the owner of the Snoop application I am not putting the complete source code here, but rather the delta and the Release binaries. In order to compile the Snoop application with my fixes first the complete source code must be downloaded from here. Then, the delta containing my fixes should be copied over the Snoop source tree. Now build it – that’s it.

The release binaries are here.

, , , , , , , , , , , , ,

share

6 Comments For This Post

  1. Shunrasoftware (Shunra Software) Says:

    New from Shunra Software: A Fix to the Awesome WPF Snoop Utility http://tinyurl.com/m4fnyk

  2. Stretch Says:

    When I run your release binaries there is no difference to the original version. I don’t see the nesting level in square brackets and changing properties has no affect. Do I still need to rebuild with your delta?

  3. Mark Kharitonov Says:

    Hi Stretch. I have checked the link and the release binaries are fine. You are probably running your old version after all. Try the following:
    1. Extract the archive contents in a dedicated directory.
    2. Run Snoop.exe from that directory.
    3. Run WpfTestApp.exe from that directory.
    4. Snoop on this app – you should see the nesting level.

  4. Stretch Says:

    Thanks Mark. I completely uninstalled my existing version and this has done the trick. If you ever get the chance to add Window layout & position persistence I would be extremely happy!

    Cheers.

  5. Mark Kharitonov Says:

    Hi Stretch. Glad you have managed. Unfortunately, I do not think I will have the resources to do what you are asking for. I just do not have any time for it. Alas!

  6. Rick Guidry Says:

    very intresting write up now to further my research

1 Trackbacks For This Post

  1. Cory Plotts’ Blog » Snoop: Now with 64-bit Support and More Says:

    [...] fixed the property editing issue in my version (see previous posts: 1, 2) with a little help from Mark Kharitonov (see this forum post for more info on [...]

Leave a Reply

Get Adobe Flash playerPlugin by wpburn.com wordpress themes