Safeguard your business and stay operational when disasters strike.

Displaying Multiple .NET Objects with WinDBG’s Command Language

Contact Us Today

While we are getting some nice tools from Microsoft for analyzing our memory, there’s still a lot of gaps where you have to resort to WinDBG and SOS. A perfect example that I’ve run into is looking at variables/types that are in different app domains because the Visual Studio debugging environment has essentially zero support for app domains. That’s normally not a problem for most people, but there’s a lot of things that you just need WinDBG and SOS to figure out. In this article I wanted to show a little trick I use with the WinDBG command language.

If you’re not familiar with WinDBG or SOS, you can watch my Introduction to WinDBG and SOS Commands and Minidump videos on WintellectNOW. Use the code JOHNR-2013 to get two free weeks of viewing pleasure.

The WinDBG command language allows you to write looping and logic statements using commands like .if, .while, .foreach, .printf, etc. You can use the command language with conditional breakpoints or write complicated analysis scripts in it. Like anything else in WinDBG, it’s barely documented and has no debugger, but a little trial and error take you a long way.

A very common situation when looking at a minidump is that you want to look at all of the objects of a particular type. In the usual case you have to copy and paste each address you find with !dumpheap –type <type>. That’s kind of tedious so here’s a quick way to dump out all the objects with the SOSEX !mdt command.

  1. .foreach (addr {!dumpheap -type Namespace.Class -short}) { !mdt addr; .echo }

It’s probably easiest to understand this from the inside out. The !dumpheap –type Namespace.Class –short, returns just the object addresses for Namespace.Class. Those address are assigned to the addr variable. The .foreach enumerates over each line of text in the addr variable and calls !mdt on each individual address. The final .echo places a blank line in the output. Below is an example where I’ll display the FontFamily types in a process.

  1. 0:013> .foreach (addr {!dumpheap -type FontFamily -short}) { !mdt addr; .echo }
  2. 000000b45faff460 (System.Drawing.FontFamily)
  3.     __identity:NULL (System.Object)
  4.     nativeFamily:000000b6aaad8f40 (System.IntPtr)
  5.     createDefaultOnFail:false (System.Boolean)
  6. 000000b45faff630 (System.Drawing.FontFamily)
  7.     __identity:NULL (System.Object)
  8.     nativeFamily:000000b6aaad8f40 (System.IntPtr)
  9.     createDefaultOnFail:false (System.Boolean)

If you run the above command, substituting your own type of course, you’ll see that the WinDBG command language is not the quickest language around. If you dump out a type with a lot of instances, you will see a lot of the BUSY in the command line. The good news is that running the command is far faster than you copy and pasting each address in yourself.

As this is a useful command, here’s a small script you can save to DumpType.txt. Note that $$ are comment characters.

  1. $$ If there’s no first argument, there’s nothing to do.
  2. .if(0 != ${/d:$arg1})
  3. {
  4.     $$ Get each address of the type into the addr variable.
  5.     .foreach (addr {!dumpheap -type ${$arg1} -short})
  6.     {
  7.         $$ Dump out this address using SOSEX.
  8.         !mdt addr;
  9.         $$ Put a line between each item dumped.
  10.         .echo
  11.     }   
  12. }
  13. .else
  14. {
  15.     .printf “nUsage: $$>>a<DumpType.txt typen”
  16. }

To run the script use the WinDBG $$>a< command to read it in and pass the parameter of the type you’d like to dump.

  1. 0:013> $$>a<c:junkDumpType.txt
  2. Usage: $$>>a<DumpType.txt type
  3. 0:013> $$>a<c:junkDumpType.txt FontFamily
  4. 000000b45faff460 (System.Drawing.FontFamily)
  5.     __identity:NULL (System.Object)
  6.     nativeFamily:000000b6aaad8f40 (System.IntPtr)
  7.     createDefaultOnFail:false (System.Boolean)
  8. 000000b45faff630 (System.Drawing.FontFamily)
  9.     __identity:NULL (System.Object)
  10.     nativeFamily:000000b6aaad8f40 (System.IntPtr)
  11.     createDefaultOnFail:false (System.Boolean)

Disasters come in many forms.

Our reliance on technology to conduct business means we are vulnerable when any event negatively impacts systems and applications. From cyber attacks and employee mistakes to power outages and earthquakes, there are many forms to events which will result in a potential disaster situation.


Assess areas of risk.

Protect systems and data.

Use proven playbooks.

Together we identify all data and backup needs along with acceptable levels of reliability.

You can rely on our extensive experience deploying solutions that meet necessary recovery objectives.

Together we maintain comprehensive documentation and set of procedures taken before, during and after a disaster.

We give you options.

Getting ahead of all events which can lead to a disaster can be done effectively. We have many options to help you achieve the right peace of mind for your business.

Explore Our Resources

Download Data Sheets, Case Studies and Infographics.
View our Videos featuring demos and customer insights.

View Resources

We deliver solutions that accelerate the value of Azure.

Ready to experience the full power of Microsoft Azure?

Start Today

Blog Home

Stay Connected

Upcoming Events

All Events