Attaching the Visual Studio Debugger to your Gadget running in the Sidebar
When working with WPF code in XBap form, things work a little differently than you may expect. Your code doesn't run in the Sidebar.exe process, it runs in a separate process named PresentationHost.exe. This isn't something new to the Vista Sidebar, this is how Internet Explorer launches XBaps in general. For more detail, see this post on the topic. Essentially what this means for Gadget debugging is that you open the Gadget in the Sidebar, open the csproj and set your breakpoints, attach to PresentationHost.exe, and then exercise the code.
Occasionally this method won't work for you because you need to debug a problem that happens during the startup or initialization portion of your code. In this case, there's a trick you can use to get attached to PresentationHost.exe before your XBap is opened. The steps are:
- Kill any existing PresentationHost.exe process. Note that this will bring down any running XBaps in a bad way. I use the command line: taskkill /f /im presentationhost.exe /fi "STATUS eq RUNNING"
- Start a new PresentationHost.exe process in a special "wait for XBap" mode: start PresentationHost.exe -embedding
- Open your project and use Debug -> Attach to Process -> PresentationHost.exe. Make sure to select "Attach To: Managed code, Native code" because before the XBap is loaded, there is no managed code in the PresentationHost.exe process.
- Set your breakpoints in your code or turn on Debug -> Exceptions per your debugging needs.
- Open the Gadget in Sidebar
I've occasionally run into problems where the debugger thinks it's attached but my breakpoints don't fire while running under Vista. This post talks about a bad interaction between Vista UAC and PresentationHost.exe that may be causing this and how to fix it. The fix (killing IE first) has always worked for me.
printf Debugging .NET
Hmm, the above sounds complex, no? It can certainly get tiring after a while, especially when coding in a tight loop. Another common technique in debugging is to use what in the olden days we referred to as "printf debugging". Before the days of "attach debugger to process" and breakpoints, you sometimes had to debug by writing status messages out as the program ran. Since this was commonly used in the early days of C programming and since the statement used to write to the console in C was named printf, this was given the nickname "printf debugging".
We could use this technique, writing a string to the console with Console.WriteLine, if we were a console application but we're not. Our next best approach is to use one of the two System.Diagnostic APIs (System.Diagnostics.Debug.WriteLine or System.Diagnostics.TraceSource.TraceInformation) to write status strings and then to view these strings using a debug output viewer like Sysinternals DebugView. This is simple enough to do and I tend to use System.Diagnostics.TraceSource in my code because this is a very flexible API which is useful for trace logging in general, not just printf debugging. A simple example of adding a trace statement to Page1.xaml.cs looks like:
using System;
using System.Diagnostics;
using System.Windows.Controls;
namespace NetNotes
{
/// <summary>
/// Interaction logic for Page1.xaml
/// </summary>
public partial class Page1 : Page
{
TraceSource trace = new TraceSource("NetNotes", SourceLevels.Information);
public Page1()
{
InitializeComponent();
trace.TraceInformation("Initialized");
}
}
}