Writing a Managed Internet Explorer Extension: Part 4–Debugging

 Mosquito Isolated on White 2Picking up where we left of with Writing a Managed Internet Explorer Extension, debugging is where I wanted to go next. I promise I’ll get to more “feature” level stuff, but when stuff goes wrong, and it will, you need to know how to use your toolset. .NET Developers typically write some code and press F5 to see it work. When an exception, the debugger, already attached, steps up to the plate and tells you everything that is wrong. When you write an Internet Explorer Extension it isn’t as simple as that. You need to attach the debugger to an existing process, and even then it won’t treat you like you’re use to. Notably, breakpoints aren’t going to launch the debugger until the debugger is already attached. So we have a few options, and some tricks up our sleeves, to get the debugger to aide us.

Explicit “Breakpoints”iebreak

The simplest way to emulate a breakpoint is to put the following code in there:

System.Diagnostics.Debugger.Break()

Think of that as a breakpoint that is baked into your code. One thing to note if you’ve never used it before is that the Break method has a [Conditional(“DEBUG”)] attribute on it – so it’ll only work if you are compiling in Debug. When this code gets hit, a fault will occur. It will ask you if you want to close, or attach a debugger. Now is your opportunity to say “I want a debugger!” and attach.

It’ll look like just a normal Internet Explorer crash, but if you probe at the details, “Problem Signature 09” will tell you if it’s a break. When working on a BHO, check this every time IE “crashes” – it’s very easy to forget that these are in there. It’s also important that you compile in Release mode when releasing to ensure none of these sneak out into the wild. The user isn’t going to look at the details and say, “Oh it’s just a breakpoint. I’ll attach and hit ‘continue’ and everything will be OK”. Once that’s done, choose Visual Studio as your debugger of choice (more on that later) and you should feel close to home.

debuggerattach

This is by far one of the easiest ways to attach a debugger, the problem with it is it requires a code change to get working, meaning you need to change the code, close all instances of IE, drop in the new DLL, restart Internet Explorer, and get it back into the state it was. A suggestion would be to attach on SetSite when the site isn’t null. (That’s when the BHO is starting up. Refresher here.) That way, your debugger is always attached throughout the lifetime of the BHO. The disadvantage of that is it’s get intrusive if you like IE as just a browser. You can always Disable the extension or run IE in Safe Mode when you want to use it as an actual browser. If you take this approach, I recommend using Debugger.Launch(). I’ll leave you to the MSDN Documents to understand the details, but Launch won’t fault the application, it will skip straight to the “Which debugger do you want to use?” dialog.

Attaching to an Existing Process

attachYou can just as well attach to an existing process like you normally would, but there is one drawback: “Which process do I want to attach to?” In IE 8 that is a question that can be difficult to answer. Each tab has it’s own process (a trend in new generation browsers – IE was the first to support it). You will have at minimum of two IE processes. One for each tab, and one per actual instance of IE acting as a conductor for the other processes. Already, with just a single tab open, you have a 50/50 chance of getting it right if you guess. Visual Studio can give us some help though. If you pull up the Attach to Process Dialog, you should see your two instances of IE. The “Type” column should give it away. We want the one with Managed code in it (after all, the title of this blog series is "Writing a Managed Extension”).

Once you’re attached, you can set regular breakpoints the normal way and they’ll get hit. Simple!

bphit

It isn’t quite as easy when you have multiple tabs open – sometimes that’s required when debugging a tricky issue. You have a few options here:

  1. When building a UI for your BHO (It’s a catch 22 – I know I haven’t gotten there yet) have it display the PID of the current process. That’s easy enough to do using the Process class. You can dumb it down a little more though and write a log file in a safe location (IE is picky where BHOs write to the File System Refresher here).
  2. Attach to all tab processes. That can lead to a lot of confusion of which tab you are currently in, because if you have two tabs open – and a breakpoint gets hit – which tab did it? The Threads Window should help you there if that is the route you choose.
  3. Always debug with a single tab, if you can.
Power Debugging

There is a trick you can do in Visual Studio to gain access to some additional debugging features. Hopefully this isn’t brand new material to everyone, but for some I would suspect it is. If you manually choose what you want to attach, include managed code and Native. Attaching to Native is very helpful if you are trying to debug a COM Marshaling issue, and plenty of other issues. We can start a the Managed Debugger Extension to diagnose issues at the CLR level, and even poke at the CLR’s native memory and objects. Once attached in Visual Studio with Native code, get to a breakpoint or pause, and launch the Immediate Window. Type .load sos and hit enter. If it worked, you should get a message like extension “C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll loaded”. There are many blogs out there about SOS (Son of Strike). I may blog on it later. Some useful commands are:

  • !help
    Pretty self explanatory. Shows you some available commands.
  • !dso (!DumpStackObjects)
    Does a dump of all CLR objects that are in the stack.
  • !dumpheap
    Dumps the entire heap. Careful! – That really means the entire heap. A more generally useful use of dumpheap is to specify the -stat flag (!dumpheap -stat). This gives you general statistics of the heap. It will tell you which objects are in memory, and how many of them there are. This is useful starting point if you believe there is a memory leak – this can at least tell you what you are leaking.
  • !soe (!StopOnException)
    Again, I feel that the name of this is pretty self explanatory. The usage of it is a little tricky to beginners. A simple example would be, “I want to stop whenever there is an OutOfMemoryException”. This is useful for some types of exception, OOM is a good example. The problem with debugging an OOM in a purely managed way is the CLR is dying by the time the exception happens, so you will get limited information by slapping a debugger on the managed code. For an OOM, a !dumpheap -stat is a good place to start. Other examples where this is useful are Access Violations (more common when doing Marshaling or Platform Invoke), Stack Overflows, and Thread Aborts. The usage is !soe -create System.AccessViolationException.
  • !CLRStack
    This will dump the CLR’s stack only. The Native stack is left out. This is the same as normal managed stacks that you have looked at. It has some cool parameters though. The -p parameter will tell you what the values of the parameters that were passed into it. Often, it will be the address of what was passed in. Use !DumpObject and pass in the address to figure out exactly what it was. The -l flag dumps the locals in the frame, and –a dumps both parameters and locals.
  • !DumpStack
    This is like CLRStack but on steroids. It has the managed stack like CLRStack, but also has the Native stack. It’s useful if you use Platform Invoke. This command is best used outside of Visual Studio and instead in something like WinDbg – more on that further down.

That’s the tip of the iceberg though. The complete documentation on MSDN is here. That lists commands that !help doesn’t list – so have a look. However, you’re not getting your money’s worth by doing this in Visual Studio. Visual Studio is great for managed debugging and using SOS, but when you want to use the Native commands, such as !analyze Visual Studio falls short. In addition, SOS is limited to the debugging functionality that Visual Studio provides it – you may often see a message like this: “Error during command: IDebugClient asked for unimplemented interface” Visual Studio doesn’t fully implement these features that SOS is asking for.

Other debuggers, like WinDbg, are significantly more powerful at the cost of they aren’t as simple to use. If there is demand for further details, I’ll post them. Using WinDbg is fairly similar, once you are attached, run .load C:\Windows\Microsoft.NET\Framework64\v4.0.30319\sos.dll. In WinDbg, you need to specify the full path. In addition, you will want to get symbols from Microsoft’s Symbol Server. There are symbols for mscoree and mscorwks. Having symbols for these can significantly help diagnose native to managed (and vice-versa) transitions.

Happy Debugging!

A Really Super Light and Simple IoC Container for Windows Phone 7

I finally managed to get the Windows Phone 7 tools installed. I’m not going to vent on that anymore because I feel like I’ve done that enough already – and once they did install correctly they’ve been very pleasurable to use. I started working on an application, and old habits die hard. I like Inversion of Control, it’s a major need for me simply because I’ve forced my mind to work like that. I’ve previously worked with Unity and Windsor. Unity has grown on me a lot, and I like it. However, none of them seem to work in Windows Phone 7, or at least they weren’t designed to. So I wrote my own really super simple IoC container for Windows Phone 7. I wanted the following features, and nothing else (for now):

  1. Able to register types such that arguments of it’s constructor are resolved
  2. Able to register an interface and type such that if the interface is resolved, the component is resolved and it’s constructor arguments are resolved
  3. Assume that there is either a default constructor or a single constructor that takes parameters
  4. Everything will have a singleton lifetime.

Super simple requirements. This will be running on phone hardware, so it needs to be lightweight, too. It fits in a single class which is about 65 lines. I’ve split it into two different files using a partial class to keep the registration separate. I can imagine some additional features that other people might want, such as a transient lifestyle, use WeakReferences if you are registering a lot of things, etc.

For the source, see the Gist on GitHub.

My Netbook Vaio P running Chrome OS – The Experience

photoI have a small little netbook, a Vaio P. It’s a cool little laptop, and I took it in favor of a clunker laptop. It handles 95% of my needs, and it’s actually pretty fast. a 128 GB solid state drive, and 2 GB of (non upgradable) RAM. It ran Windows 7 perfectly, only hiccupping on performance when it came to video and medium to large Visual Studio solutions. But I didn’t get it for development, I got it for a browser and a chat client (this was pre-iPad days). I figured if all I used it for was that, most of the time just a browser, I owed it to myself to try installing Chrome OS.

I’d previously played with it in a Virtual Machine, and was very impressed by the boot time (it boots faster than the BIOS can do a POST). It’s borderline an instant-on operating system. That’s typically what I use it for – open it up, use a browser for 30 seconds to figure something out, and then I am done. For Windows, it’ll go into standby, but ends up in hibernate pretty quick because my battery desperately needs to be replaced. I’m impatient, I want it on now. That’s what Chrome OS seemed to offer.

Installing Chrome OS is not nearly as simple as installing another distribution. In fact, it has no installer. Going even further, there isn’t an official build of it yet. I ended up getting the Flow version from Hexxeh. Basically you are given an IMG file, which is a drive image. You have to image it to something, I used a USB Key per the instructions. Having another Linux distribution is close to required – you need grub to boot, and an easy way to copy partitions (dd). First, in Windows 7, I used Computer Management to get rid of all of the partitions I didn’t need (like the recovery one) and the other one that Windows 7 likes to use for BitLocker purposes. I just used BCDEdit to make the main partition bootable. Doing this from Windows 7 is highly preferable because while GPart can resize an NTFS Partition, it will often make Windows unhappy and require that you repair the boot loader. I ended up with a drive that had 7 GB free in the front, then the NTFS volume for Windows 7. I shrunk the Windows 7 partition by 3 GB and left those 3 GB unallocated. I installed Ubuntu on the 7 GB space in the front (which works great by the way, more on that later), and the other 3 GB would be for Chrome. I won’t go into the details of installing Chrome because I think the documentation is pretty good, but if you fear spending an angering hour with grub when something might go wrong or don’t want to risk destroying all of your partitions, this may not be for you.

In the end, I got everything working correctly. The first thing you will notice is that Chrome OS requires an internet connection to login. But you need to login to configure WiFi. Fortunately, I have the Ethernet / VGA adapter for it so I just plugged in, logged in, then configured WiFi. Alternatively, you could use the username “facepunch” and the password “facepunch” to login an configure your WiFi… which leads me to my first point. Hexxeh, as he goes by, is a 17-year-old kid. A brilliant one at that. However, I have reservations about the safety of these distributions. I’m not doubting him, but he could, like any other person including me, make a mistake. He could be doing worse and harvesting passwords. The 17-year-old me would find “facepunch” funny (and the current me does, too) but it sends a bit of a mixed message.

After getting logged in, you’ll go through a few EULAs, all of which are for Java. After that, you’re done! Unfortunately, that’s as far as I got really. It was dirt slow. Actually unusable. This isn’t Hexxeh’s fault either. I’d put most of the blame, if not all of it, on the lack of proper video drivers for the Intel GMA 500. If you installed a Linux distribution on your Vaio P you know you have to do a few magic tricks to get your video card working at something other than awful. With Chrome OS, that isn’t really an option due to the partition layout. It was disappointing, quite a bit a work for a net loss. When Chrome OS goes live, hopefully I can try again. This little laptop will always have a home in my tech closet.

On a related topic, Ubuntu 10.10 works great on it. There is one trick to getting it installed. I could only get the installer to work correctly was from a NetInstall using UNetbootin. Directly from a USB Key resulted in the error “(initramfs) Unable to find a medium containing a live file system.” Basically even though it just booted from USB, it couldn’t read from it. On top of that, once I was booted into the setup, it couldn’t figure out my WiFi so everything had to be downloaded via LAN. Once I got that far, everything went smooth. Take the time to straighten out the video drivers and you’ll be happy. My feeling on performance was basically “Ubuntu boots faster than Windows 7 but runs slower (noticeably) once booted.” I’m sure there are a lot more tweaks I can do to get this working better. We’ll see! I know, “real” Linux guys will tell you, “If you are after performance, why the hell did you install Ubuntu?” Yeah, I know. Maybe I’ll try another one later.

The verdict on Chrome OS is don’t bother with Hexxeh’s flow build. Wait for a newer one. Ubuntu is worth a shot though.