Snoop Now Works in WPF Interop Scenarios, Part I

Background:

Coming from the land of Windows Forms, I have grown addicted to having tools like wfSpy and Hawkeye. A software engineer at the presentation layer needs to have tools like these in order to inspect the objects in a running application and change properties on the fly.

Very soon after jumping in head first into WPF, I discovered Pete Blois’ utility: Snoop. It was definitely what I was looking for. Unfortunately, after playing with it for a while, I learned that it didn’t support our WPF interop scenario. In particular, our application is a Windows Forms application that is hosting WPF content through ElementHost. When you use ElementHost, you don’t have an Application object and Snoop coughs up a hairball because of that.

After that, Josh Smith created Woodstock and Mole soon followed. These are both debugger visualizers, and in particular, Mole is extremely nice and powerful. The Achilles tendon of debugger visualizers, however, is that you have to be running in the Visual Studio debugger. There are many cases where you can’t or don’t want to do this.

Josh Smith realized this and has created Crack.NET. This is a heap walker in the vein of Snoop and Mole … but it can be run outside of the debugger. It is a useful tool in its own right, and of particular note, you can modify the object you’ve ‘cracked’ using IronPython in the tool’s Scriptorium area.

However, even given the above, I was still missing the functionality of good, old wfSpy. Snoop was very close to what I wanted, it just didn’t handle the WPF interop story.

So, after reading this post in the WPF forums, I finally broke down, dove into the source code and figured out why. It was rather easy to fix, actually, and here is what I had to do.

 

The Fix:

In the Enqueue method of the DelayedCall class, you need to get hold of the Dispatcher from something other than the Application.Current object. Here is the whole Enqueue method:

public void Enqueue()
{
    if (!this.queued)
    {
        this.queued = true;

        Dispatcher dispatcher = null;
        if (Application.Current == null)
            dispatcher = Dispatcher.CurrentDispatcher;
        else
            dispatcher = Application.Current.Dispatcher;

        dispatcher.BeginInvoke
        (
            this.priority,
            new DispatcherOperationCallback(this.Process),
            null
        );
    }
}


In the Inspect method of the SnoopUI class, you once again need to protect yourself from not having an Application object:

public void Inspect(object target)
{
    this.rootObject = target;
    this.Load(target);
    this.CurrentSelection = this.root;

    this.OnPropertyChanged("Root");

    if (Application.Current != null)
        this.Owner = Application.Current.MainWindow;
    this.Show();
}

After those two changes, you can Snoop WPF content hosted in a Windows Forms application through ElementHost. Do I hear a ‘hallelujah’?

On a related note:

One thing I should mention is that property editing is broken in Snoop 2.0. In the WPF forum post mentioned above, Mark points out how to fix this. You just need to add the following line in the correct place in the PropertyInformation constructor:

binding.Mode =
	property.IsReadOnly ?
	BindingMode.OneWay :
	BindingMode.TwoWay;

However, this doesn’t seem to fix it completely when you are running in a WPF interop scenario … because there is still an issue to find and fix. Namely, you can’t use the keyboard to modify the property values. However, I have discovered that you can paste a value in using the clipboard. If you find out how to fix this, please let me know.

Finally:

Mark also has fixes for a couple other items. One takes care of an issue when the nesting gets too deep and another is a fix for popping the context after you ‘delve’ in on something.

I hope this helps someone. I personally am happy to the point of tears that I will now be able to Snoop our application!

Update:

I have found the keyboard issue and have fixed it. I have also uncovered a couple other changes that you need to make. For example, the Previewer wasn’t working. See my next blog post for details.

Update:

(The source code and binaries for Snoop are now (see posts: 1, 2) up on CodePlex. Please go download it from there as that code will contain the latest and greatest bits.)

GPU Effects & Blurry Text

About a month ago, I ran into a weird issue … that literally confounded me … and irked me to no end. The issue was that whenever I applied a drop shadow effect to a border that contained text … the text would blur a little bit.

So, if I did the following:

<Window
    x:Class="EffectsAndBlurryText.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Effects and Blurry Text (Good)"
    Height="300"
    Width="500"
>
    <Grid>
        <Border
            Margin="20"
            Background="White"
            BorderBrush="DarkBlue"
            BorderThickness="3"
            CornerRadius="25"
        >
            <TextBlock
                Text="This text is not blurry."
                FontSize="24"
                TextWrapping="Wrap"
                Foreground="DarkBlue"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
            />
        </Border>
    </Grid>
</Window>

I would get nice looking text:

ClearText

 

But if I added the drop shadow effect:

<Window
    x:Class="EffectsAndBlurryText.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Effects and Blurry Text (Bad)"
    Height="300"
    Width="500"
>
    <Grid>
        <Border
            Margin="20"
            Background="White"
            BorderBrush="DarkBlue"
            BorderThickness="3"
            CornerRadius="25"
        >
            <Border.Effect>
                <DropShadowEffect Color="DarkGray"/>
            </Border.Effect>
            <TextBlock
                Text="Why, oh, why is this text blurry?"
                FontSize="24"
                TextWrapping="Wrap"
                Foreground="DarkBlue"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
            />
        </Border>
    </Grid>
</Window>

I would get blurry text (click on the image to better see the issue):

BlurryText

 

So, how can we get around this annoying issue? Here is what I came up with: wrap the Border in a Grid and put another Border underneath the one you had originally. Put the BorderBrush and Background on the new Border and apply the drop shadow effect there instead.

Here is the xaml:

<Window
    x:Class="EffectsAndBlurryText.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Effects and Blurry Text (Fixed)"
    Height="300"
    Width="500"
>
    <Grid>
        <Border
            Margin="20"
            BorderThickness="3"
            CornerRadius="25"
            Background="White"
            BorderBrush="DarkBlue"
        >
            <Border.Effect>
                <DropShadowEffect Color="DarkGray"/>
            </Border.Effect>
        </Border>
        <Border
            Margin="20"
            BorderThickness="3"
            CornerRadius="25"
        >
            <TextBlock
                Text="Ah, now, the text is not blurry."
                FontSize="24"
                TextWrapping="Wrap"
                Foreground="DarkBlue"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
            />
        </Border>
    </Grid>
</Window>

 

I would love to hear if anyone has any better ideas to solve this … or just if others have noticed it as well.

I hope this helps someone … I know at least one other person has run into this. See his January 28th blog entry.

 

Note: this issue seems intermittent at times. In particular, sometimes you can see it only in the designer (both Visual Studio and Blend). However, that being said, it is not just in the designer … I have seen it in running executables.

Update 1: Others seem to have run into this issue as well. There is a current forum post about this, in fact.

Update 2: Initially, I thought this was an NVIDIA driver issue, but others have seen it on ATI cards and Intel integrated solutions. Walt Ritscher says its a known issue. I wonder if it is related to another issue that I’ve had.

Kaxaml: Don’t Leave Home Without It

KaxamlLogo

Ok, I just have to give a shout out to one of the best tools out there for authoring loose xaml. And, if the logo didn’t give it away … it’s Robby Ingebretsen’s Kaxaml tool. It is available here for download … free of charge!

It’s been out for quite some time … so the purpose of this blog post is really to just publicly thank him for making such an awesome tool … one, in fact, that I don’t leave home without.

Recently, I have been composing Haikus … just because a tool like this … deserves poetry … and poetry better than mine!

But, in case you haven’t heard about it or haven’t played with it much … here is some quick info. I believe you pronounce it <ka-zam-al> … and I like to think like Shazam! Pow! (I have not confirmed this was the intent of its author … it might just be the meanderings of this crazy mind of mine.)

It has a pretty sweet list of features:

  • A snippet library with the ability to insert snippets via shortcut
  • IntelliSense
  • A folding editor
  • An integrated color picker
  • A xaml scrubber (or pretty printer or formatter or whatever you want to call it)
  • The ability to zoom in and out on your rendered xaml
  • The ability to make your xaml larger (use ctrl-wheel)
  • Handles both WPF and Silverlight
  • And more!
    Bonus: Robby recently recorded several videos that will bring you up to Kaxaml power user status in a matter of minutes. Check them out.

Disabling Optimizations when Debugging .NET Framework Source Code

Ok, you think you’re cool when you get the capability to debug the .NET Framework source code all set up. You’re like, “I am all powerful!” Then you start noticing the oddities ….

“Wait, why I can’t get the value of that variable?!”

“Why did it step there? It should have stepped here?!”

 

The problem is that ‘you’re debugging against retail-optimized code’. Fortunately, someone at Microsoft handed out the trick to disable these optimizations. Check out this link for more info, but basically there are only a few steps:

  • Create a .cmd file that sets an environment variable and then launches Visual Studio. Name it whatever you want (e.g. DisableOptimizationsInVisualStudio.cmd). It’s contents should be:
set COMPLUS_ZapDisable=1
cd /d "%ProgramFiles%\Microsoft Visual Studio 9.0\Common7\ide\"
start devenv.exe
exit
  • Launch Visual Studio with this .cmd file.
  • Once in Visual Studio, disable the Visual Studio hosting process:

Right click on your project and choose “Properties”.
Choose the “Debug” tab and uncheck “Enable the Visual Studio Hosting Process”.

  • Launch your application in the debugger.

 

Once again, you are all-powerful.

 

For more information (in reverse chronological order):

  • Apparently, you can now get all the source code, at once, from Microsoft and without having to resort to the .NET Mass Downloader. I have not tried this yet, but check out this link for more info.
  • The CodePlex site for the .NET Mass Downloader
  • John Robbins’ blog post about the 1.5 version of the .NET Mass Downloader
  • John Robbins’ blog post about the 1.2 version of the .NET Mass Downloader
  • John Robbins’ blog post about the 1.1 version of the .NET Mass Downloader
  • The initial release of the .NET Mass Downloader by John Robbins and Kerem Kusmezer
  • Shawn Burke’s original post on how to configure Visual Studio to debug .NET Framework source code

I should also mention that I used the .NET Mass Downloader on the following directories in order to pull down .NET 2.0, .NET 3.0, and .NET 3.5. I was not aware (prior) that most of the assemblies for .NET 3.0 and .NET 3.5 were at “C:\Program Files\Reference Assemblies\Microsoft\Framework”. That represents a departure from the original location at “C:\Windows\Microsoft.NET\Framework”.

  • C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
  • C:\WINDOWS\Microsoft.NET\Framework\v3.0
  • C:\WINDOWS\Microsoft.NET\Framework\v3.5
  • C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0
  • C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5

Make System.Windows.Forms.Button into a RepeatButton

Recently, I was trying to get caught up on my blog reading and read Scott Hanselman’s blog post about SyntaxHighlighter. Well, this encouraged me to install Windows Live Writer and try this plugin out. (I was always bothered that I had to create pngs with my code snippets in them for my blog post on name scopes in WPF.)

Well, I quickly found out that a blog at www.wordpress.com can not use plugins. Argh. So, I finally broke down, decided to register a domain, and installed WordPress to it.

So, this post is really a test of whether I have correctly set up Alex Gorbatchev’s SyntaxHighlighter, but I thought I would go ahead and post something interesting as well. So, without further adieu:

Recently, I thought … “I love WPF’s RepeatButton. How can I make the System.Windows.Forms.Button into a RepeatButton?”

So here is some code to do that:

public class RepeatButton : System.Windows.Forms.Button
{
    protected override void OnMouseDown(MouseEventArgs e)
    {
        base.OnMouseDown(e);

        if (e.Button == MouseButtons.Left)
        {
            OnClick(EventArgs.Empty);
            RepeatButton.repeatButtonTimer.Tick += new EventHandler(repeatButtonTimer_Tick);
            repeatButtonTimer.Start();
        }
    }
    protected override void OnMouseUp(MouseEventArgs e)
    {
        this.mousingUp = true;

        base.OnMouseUp(e);

        if (e.Button == MouseButtons.Left)
        {
            repeatButtonTimer.Stop();
            RepeatButton.repeatButtonTimer.Tick -= new EventHandler(repeatButtonTimer_Tick);
        }

        this.mousingUp = false;
    }

    protected override void OnClick(EventArgs e)
    {
        if (this.mousingUp) return;

        base.OnClick(e);
    }

    private void repeatButtonTimer_Tick(object sender, EventArgs e)
    {
        OnClick(EventArgs.Empty);
    }

    private bool mousingUp = false;

    static RepeatButton()
    {
        repeatButtonTimer.Interval = 250;
    }
    private static System.Windows.Forms.Timer repeatButtonTimer = new Timer();
}

Ctrl-K, Ctrl-D: Reformatting XAML in VS 2008

StackOverflow is continuing to prove its usefulness. Today, I ran across a post about reformatting xaml. Being very meticulous (ok, obsessive/compulsive <grin>) about this sort of thing, it caught my eye.

One of things, I have loved Kaxaml for is its xaml scrubber (formatter).

However, I have always wanted to have this ability in Visual Studio. Well, you do (at least in VS 2008, I haven’t checked VS 2005). Check out Laurent’s blog post on it.

Dr. WPF & Namescopes

Ok, let me first say that Dr. WPF is my hero. Not just because of his WPF snippet library. But especially because of his community involvement in the WPF forum.

Today, I was wracking my brain against a problem that I’ve never run into before and … and it was Dr. WPF to the rescue (via the forum).

The Problem:

I have a custom control that I was retemplating with a fancy, schmancy template. This ControlTemplate had a Resources section where I had a couple Storyboards which were targeting items in the visual tree of the fancy template. I was also launching this Storyboard from the code for the custom control.

However for some reason, it couldn’t resolve the Storyboard.TargetName(s). It kept coming back with the error: ‘<Storyboard.TargetName>’ name cannot be found in the name scope of ‘<Namespace.CustomControl>’.

(This is where the hair pulling happened.)

The Solution:

After some research: here, here, and here … I stumbled across Dr. WPF’s forum answer on the matter. That led me to look very closely at how I was calling the Begin on the Storyboard.

Here is the old and bad code:

And, here is the good code:

What did I do differently? Well, I had always thought that the argument to the Begin method above was an object containing the items that are being targeted by the Storyboard … and that is what the IntelliSense parameter tends to suggest (containingObject) …

However, looking closer at the documentation on the parameter it says: An object contained within the same name scope as the targets of this Storyboard’s animations. Ah, ha!

After that, all I had to do was grab one of the elements in the visual tree (_button in the above code snippet) and pass that to the Begin method (whereas before I was just passing the custom control instance in, the ‘this’ in the first code snippet above).

And all of this is due to a friendly answer by the good doctor.

Thanks Doc!

Update:

I think there is another and better way to solve this problem. Check out this question/answer on StackOverflow. Bascially, there is an overload to the Begin method that lets you send in the control template. Nice. Don’t know how I missed that overload.

Encodings Matter with .fx Files

I was tearing my hair out, trying to figure out why my .fx file wasn’t compiling with fxc.

Eventually I figured out that if I saved the .fx file with a text editor (TextPad), fxc would just work … (previously I was saving this file using Visual Studio).

Ok, by chance I ran across Pavan Podila’s post on the matter. Ah, that’s why!

Apparently, the default encoding for text files is Unicode (UTF-8 with signature) – Codepage 65001 … and apparently fxc doesn’t compile .fx files if they have his encoding.

Argh! Wish I had seen that post sooner.

Some good news on the matter, however, is that the Visual Studio templates that Greg Schechter has posted on his blog … set the encoding to Western European (Windows) – Codepage 1252 … which does compile.

So, if you use these templates, you won’t have to think about it … which is a good thing.