Category Archives: Version 7.3

.NET Reflector 7.3 Released, Including BAML to XAML Decompilation

Somewhat ahead of schedule – I wasn’t planning this until September – we’ve released .NET Reflector 7.3. The reason for the headlong rush into another point release a mere week after the last one was a critical bug that came to light shortly after we released 7.2.

Before going any further though, I ought to point out the other exciting news about .NET Reflector 7.3, which is that it includes BAML to XAML decompilation in the core product. I know a lot of you have been hoping for this for a while, so we’re really excited it’s now in there. Here’s what it looks like:

Reflector7_3EA1_BAMLtoXAML[1]

Expect to see this improved in future releases as well but, for now, back to that bug…

We discovered that, if an assembly were opened using the Browse with .NET Reflector shell integration option from Windows Explorer, Reflector would often hang on some systems. Related to this, we had a report of the same behaviour come in from somebody trying to start Reflector from Visual Studio: http://forums.reflector.net/questions/1068/opening-reflector-from-vs2008-doesnt-work.

The problem turned out to be quite an interesting one.

When you open Reflector from either the shell, or from within Visual Studio, the new instance does a check to see if any instance of Reflector is currently running. If it is, then it’ll pass a command over telling the instance that’s already running to open your assembly, type, or member. To find other running instances of Reflector it turns out we iterate through the windows for running applications and examine the title bar text:

private IntPtr targetWindow = IntPtr.Zero;
 
 
private bool EnumWindow(IntPtr handle, int lparam)
{
	uint	windowProcessID;
	NativeMethods.GetWindowThreadProcessId( handle, out windowProcessID );
	StringBuilder titleBuilder = new StringBuilder(256);
	NativeMethods.GetWindowText(handle, titleBuilder, 256);
	if (titleBuilder.ToString().StartsWith(".NET Reflector 7"))
	{
		targetWindow = handle;
	}
	return true;
}

 

It turned out that the GetWindowText call was hanging, so I did a bit of digging and found this rather interesting relic posted eight years ago by Raymond Chen: http://blogs.msdn.com/b/oldnewthing/archive/2003/08/21/54675.aspx.

Apparently GetWindowText will hang if you try to get the text for a window your process owns that is hung for some reason. Well, OK, that’s weird, but I don’t want to find windows belonging to my own process anyway so, cowboy coder hat on, I made the following changes:

private IntPtr targetWindow = IntPtr.Zero;
 
 
private Process	m_ThisProcess;
 
 
private bool SendCopyDataMessage( string message )
{
	

	m_ThisProcess = Process.GetCurrentProcess();

	if ( targetWindow == IntPtr.Zero )
	{
		targetWindow = IntPtr.Zero;
		NativeMethods.EnumWindows( new NativeMethods.EnumWindowsCallback( EnumWindow ), 0 );
	}
 
	if ( targetWindow != IntPtr.Zero )
	{
		// Send message
 	}
 
	m_ThisProcess.Dispose();

	return false;
}
 
 
private bool EnumWindow(IntPtr handle, int lparam)
{
	uint	windowProcessID;
	NativeMethods.GetWindowThreadProcessId( handle, out windowProcessID );
 
	// Only identify a Reflector window that DOESN’T belong to this process
        if ( m_ThisProcess.Id != windowProcessID )
	{
		StringBuilder titleBuilder = new StringBuilder(256);
		NativeMethods.GetWindowText(handle, titleBuilder, 256);
		if (titleBuilder.ToString().StartsWith(".NET Reflector 7"))
		{
			targetWindow = handle;
		}
	}
			
	return true;
}

 

So now all I do is make sure the window doesn’t belong to the running process before I check whether or not it’s a Reflector window.

But why had the window been created anyway at this point?

And why was it hanging?

You may be aware that we did a lot of work on Reflector’s start-up sequence for 7.2, including hiving off a lot of work onto a background thread to ensure that the application window appears as quickly as possible.

Unfortunately this introduced the potential for a race condition where the requested assembly was loaded but the assembly browser tree view hadn’t been updated on the foreground thread to make sure the assembly was visible. Thus, when we tried to select the assembly in the tree view, Reflector couldn’t find it there and popped up an error message. The modal error dialog was causing, one presumes, the main window to be hung, and thus GetWindowText hung.

We then fixed the treeview to make sure it was updated before attempting to select the item. We did the same for the Visual Studio integration to fix the problem reported on the forums, but then ran into another problem because we were getting a zombie tab, which turned out to be because there was one call to remove a tab we hadn’t checked was marshalled on the Dispatcher thread before invoking it.

We then found one final race condition that could cause a NullReferenceException if Reflector needed to unload an assembly when side-by-side versioning was disabled. The fix to make that code thread safe was fairly straightforward though, and now everything appears to be working fine again.

We did however want to take a little more time for testing before releasing 7.3 into the wild. Since all appears to be well we’ve now put this build out and would recommend you upgrade from 7.2 as soon as you’re able. We also apologise for any inconvenience you might have experienced as a result of these problems over the past week. You’ll be pleased to note that we’ve updated our test plan to try to ensure these problems don’t come up again.

As ever, you can download the build from the www.reflector.net homepage, or get it via the Help > Check for Updates main menu item in .NET Reflector itself.

.NET Reflector 7.2 has been released, and a .NET Reflector 7.3 EA build, including BAML decompilation, is now available

I’m very pleased to announce that .NET Reflector 7.2 has been released. You can get it via the main download link on the homepage at www.reflector.net.

Highlights include:

I’m also pleased to be able to announce the release of the first .NET Reflector 7.3 early access build, which includes BAML to XAML decompilation. This isn’t yet perfect but as you can see from this screenshot it works pretty well:

Reflector7_3EA1_BAMLtoXAML

(We’ll obviously sort out the formatting in due course.)

You can get the 7.3 EA build from the EA download link at the bottom of the www.reflector.net homepage.