Reference

Debugging ActiveX Controls in Internet Explorer 8

Debugging ActiveX controls in Internet Explorer 8 has become a little bit more complicated compared to previous versions of the browser. In IE 5, 6 and 7 it was sufficient to host the ActiveX control in a web site and hit the F5 key from within Visual Studio. In the latest browser version this no longer possible, because of the browser’s new process model. This article describes the few extra steps required to attach Visual Studio to a debug session and enable breakpoints and other features.

Tags: activex com c++ debugging internetexplorer visualstudio

Overview

In previous versions of Internet Explorer, including IE7, each browser window has its own process, and all tabs within that window share the process of the window they’re hosted in. A failure in any of the open tabs or installed add-ons will cause all other tabs to become dysfunctional, but this model is convenient for developers, because they can simply attach a debugger to the main window in order to debug web pages and embedded controls. In particular, development environments can be configured to launch the browser as part of a debugging session, and the debugger will automatically attach to the right process.

In order to improve the stability, performance and scalability, IE8 implements a new process model called Loosely-Coupled IE (LCIE). The default settings create one process for the window frame and additional processes for the tabs. All these processes are isolated; communication between them is handled asynchronously. As a result, the process hosting a web page is not the same as the browser window’s process. Hence, debuggers are no longer able to attach to the correct process automatically.

Attaching To The Correct Process

Although there is no way to automatically attach Visual Studio to the correct web browser process, it is still possible to attach the debugger manually by selecting Debug → Attach to Process… from the main menu.

If the web site to be debugged is the only one currently open, selecting the right process ID for attachment is easy. Since one process is created for the browser window and another one for the tab containing the web page, there will be only two processes running. Obviously, the one to be selected is the one that does not have a window title.

In practice, however, a developer will have multiple browser windows with multiple tabs open. Unfortunately, the Attach to Process window only lists all running processes and does not show their hierarchy. One can either try to guess the correct process ID or use a task manager that provides a hierarchical view, such as Process Explorer. Note that the parent process for the browser window depends on where the browser was launched from, as shown in the screenshot on the right.

Controlling IE’s Process Management

Internet Explorer 8 also provides a way to control how processes are created for new browser tabs. Developers may be particularly interested in the option to run all tabs and the window frame in a single process, similarly to how it is done in older browser versions. This option can be enabled in the Windows Registry by performing the following steps:

  1. Click the Start button, select Run…, and enter regedit to launch the Registry Editor
  2. Navigate to the key HKEY_CURRENT_USER → Software → Microsoft → Internet Explorer → Main
  3. Open or create the DWORD value TabProcGrowth and enter a value of 0.

Internet Explorer needs to be restarted for the value to take effect.

Using Assertions to Attach the Debugger

Another, somewhat less elegant way is to attach the browser to Visual Studio by throwing an assertion from within the website, i.e. in a hosted ActiveX control. In C++ this can easily be accomplished by calling the assert() macro in the control’s initialization routines or constructors.

#include <assert.h>

assert(false);

The assertion will cause the browser to show an error message with the option to attach to a running instance of Visual Studio.

Logging To Console

When the Visual Studio debugger is attached to the browser process, output and tracing information will conveniently be routed to Visual Studio’s Output window. Developers who are interested in logging functionally only may avoid attaching to Visual Studio alltogether and log the ActiveX control’s output to a console window instead. In C++, a console window can be created using the AllocConsole() function:

#include <windows.h>
#include <stdio.h>

if (AllocConsole())
{
   freopen("CONOUT$", "w", stdout);
   SetConsoleTitle("Debug Console");
}

Debug information can now be printed to stdout and will show up in the console window.

Logging To File

In some cases it may be useful to log debug information to a file. There is a plethora of logging and tracing libraries available on the internet. A very simple logging class with Unicode support for inclusion in a C++ project may look like the following:

#include <stdio.h>
#include <stdarg.h>
#include <tchar.h>

class LogFile
{
public:

   LogFile (const char* filename)
   {
       fopen_s(&logFile, filename, "a");
   }

   ~LogFile ()
   {
       if (logFile != NULL)
       {
           fclose(logFile);
           logFile = NULL;
       }
   }

   void Logf (TCHAR* format, …)
   {
       if (logFile != NULL)
       {
           va_list args;
           va_start(args, format);

           TCHAR buff[1023];

           _vsntprintf_s(buff, sizeof(buff), format, args);

           Log(buff);
       }
   }

protected:

   FILE* logFile;
};

Related Resources