Ironpython Interacting with COM Objects

An Overview of COM Access Differences with Python

COM access is an area where IronPython and Python take completely different approaches. In fact, it’s safe to say that any Python code you want to use definitely won’t work in IronPython. Python developers normally rely on a library such as Python for Windows Extensions ( projects/pywin32/). This is a library originally created by Mark Hammond (http://starship that includes not only the COM support but also a really nice Python editor. You can see a basic example of using this library to access COM at http://www Even if you download the required library and try to follow the tutorial, you won’t get past step 1. The tutorial works fine with standard Python, but doesn’t work at all with IronPython.

It’s important to remember that IronPython is a constantly moving target. The developers who support IronPython constantly come out with new features and functionality, as do the third parties that support it. You may find at some point that there’s a COM interoperability solution that does work for both Python and IronPython. The solution doesn’t exist today, but there’s always hope for tomorrow. If you do encounter such a solution, please be sure to contact me at [email protected]

Fortunately, IronPython developers aren’t left out in the cold. COM support is built right into IronPython in the form of the .NET Framework. An IronPython developer uses the same techniques as a C# or a Visual Basic.NET developer uses to access COM — at least at a code level.

When you work with COM in Visual Studio in either a C# or Visual Basic.NET project, the IDE does a lot of the work for you. If you want to use a COM component in your application, you right-click References in Solution Explorer and choose Add Reference from the context menu. At this point, you see the Add Reference dialog box where you choose the COM tab shown in Figure 9-1.

When you highlight an item, such as the Windows Media Player, and click OK, the IDE adds the COM component to the References folder of Solution Explorer, as shown in Figure 9-2. The IDE writes code for you in the background that adds the COM component and makes it accessible. You’ll find this code in the .CSProj file and it looks something like this:

<COMReference Include=”MediaPlayer”>

Fi gure 9-1: The Add Reference dialog box provides you with a list of COM components you can use.

In addition, the IDE creates Interop.MediaPlayer.DLL, which resides in the project’s objx86Debug or objx86Release folder. This interoperability (interop for short) assembly makes it easy for you to access the COM component features.

Any reference you add appears in the References folder of Solution Explorer.

Of course, if the COM component you want to use is actually a control, you right-click the Toolbox instead and select Choose Items from the context menu. The COM Components tab looks much like the one shown in Figure 9-3.

In this case, check the controls you want to use and click OK. Again, the IDE does some work for you in the background to make the control accessible and usable. For example, it creates the same interop assembly as it would for a reference. You’ll see the control in the Toolbox, as shown in Figure 9-4.

The tasks that the IDE performs for you as part of adding a reference or Toolbox item when working with C# or Visual Basic.NET are manual tasks when working with IronPython. As you might imagine, all of this manual labor makes IronPython harder to use with COM than when you work with Python. While a Python developer simply imports a module and then writes a little specialized code, you’re saddled with creating interop assemblies and jumping through coding hoops.

COM components and controls can also appear in the Choose Toolbox Items dialog box.

The control or controls you selected appear in the Toolbox.

You do get something for the extra work, though. IronPython provides considerably more flexibility than Python does and you can use IronPython in more places. For example, you might find it hard to access Word directly in Python. The bottom line is that IronPython and Python are incompatible when it comes to COM support, so you can’t use all the online Python sources of information you normally rely on when performing a new task.

Choosing a Binding Technique

Before you can use a COM component, you must bind to it (create a connection to it). The act of binding gives you access to an instance of the component. You use binding to work with COM because, in actuality, you’re taking over another application. For example, you can use COM to create a copy of Word, do some work with it, save the resulting file, and then close Word — all without user interaction. A mistake that many developers make is thinking of COM as just another sort of class, but it works differently and you need to think about it differently. For the purposes of working with COM in IronPython, the act of binding properly is one of the more important issues. The following sections describe binding in further detail.

Understanding Early and Late Binding

When you work with a class, you create an instance of the class, set the resulting object’s properties, and then use methods to perform a particular task. COM lets you perform essentially the same set of steps in a process called early binding. When you work with early binding, you define how to access the COM object during design time. In order to do this, you instantiate an object based on the COM class.

These sections provide an extremely simplified view of COM. You can easily become mired in all kinds of details when working with COM because COM has been around for so long. For example, COM supports multiple interface types, which in turn determines the kind of binding you can perform. This chapter looks at just the information you need to work with COM from IronPython. If you want a better overview of COM, check the site at library/ms809980.aspx. In fact, you can find an entire list of COM topics at

The COM approach relies on a technique called a virtual table (vtable) — essentially a list of interfaces that you can access, with IUnknown as the interface that’s common to all COM components. Your application gains access to the IUnknown interface and then calls the queryinterface() method to obtain a list of other interfaces that the component supports (you can read more about this method at Using this approach means that your application can understand a component without really knowing anything about it at the outset.

It’s also possible to tell COM to create an instance of an object after the application is already running. This kind of access is called late binding because you bind after the application starts. In order to support late binding, a COM component must support the IDispatch interface. This interface lets you create the object using CreateObject(). Visual Basic was the first language product to rely on late binding. You can read more about IDispatch at ms221608.aspx.

Late binding also offers the opportunity to gain access to a running copy of a COM component. For example, if the system currently has a copy of Excel running, you can access that copy, rather than create a new Excel object. In this case, you use GetObject() instead of CreateObject() to work with the object. If you call GetObject() where there isn’t any copy of the component already executing, you get an error message — Windows doesn’t automatically start a new copy of the application for you.

If a COM component supports both the vtable and IDispatch technologies, then it has a dual interface that works with any current application language. Most COM components today are dual interface because adding both technologies is relatively easy and developers want to provide the greatest exposure for their components. However, it’s always a good idea to consider the kind of binding that your component supports. You can read more about dual interfaces at ekfyh289.aspx.

Using Early Binding

As previously mentioned, using early binding means creating a reference to the COM component and then using that reference to interact with the component. IronPython doesn’t support the standard methods of early binding that you might have used in other languages. What you do instead is create an interoperability DLL and then import that DLL into your application. The “Defining an Interop DLL” section of the chapter describes this process in considerably more detail. Early binding provides the following benefits:

  • Faster execution: Generally, your application will execute faster if you use early binding because you rely on compiled code for the interop assembly. However, you won’t get the large benefits in speed that you see when working with C# or Visual Basic.NET because IronPython itself is interpreted.
  • Easier debugging: In most cases, using early binding reduces the complexity of your application, making it easier to debug. In addition, because much of the access code for the COM component resides in the interop assembly, you won’t have to worry about debugging it.
  • Fuller component access: Even though both early and late binding provide access to the component interfaces, trying to work through those interfaces in IronPython is hard. Using early binding provides you with tools that you can use to explore the interop assembly, and therefore discover more about the component before you use it.
  • Better access to enumerations and constants: Using early binding provides you with access to features that you might not be able to access when using late binding. In some cases, IronPython will actually hide features such as enumerations or constants when using late binding.

Using Late Binding

When using late binding, you create a connection to the COM component at run time by creating a new object or reusing a running object. Some developers prefer this kind of access because it’s less error prone than early binding where you might not know about runtime issues during design time. Here are some other reasons that you might use late binding.

  • More connectivity options: You can use late binding to create a connection to a new instance of a COM component (see the “Performing Late Binding Using Activator.CreateInstance()” section of this chapter) or a running instance of the COM component
  • Fewer modules: When you use late binding, you don’t need an interop assembly for each of the COM components you want to use, which decreases the size and complexity of your application.
  • Better version independence: Late binding relies on registry entries to make the connection. Consequently, when Windows looks up the string you use to specify the application, it looks for any application that satisfies that string. If you specify the Microsoft Excel 9.0 Object Library COM component (Office 2000 specific), Windows will substitute any newer version of Office on the system for the component you requested.
  • Fewer potential compatibility issues: Some environments don’t work well with interop assemblies. For example, you might be using IronPython within a Web-based application. In this case, the client machine would already have to have the interop assembly, too, and it probably doesn’t. In this case, using late binding allows your application to continue working when early binding would fail.

Defining an Interop DLL

Before you can do much with COM, you need to provide some means for .NET (managed code) and the component (native code) to talk. The wrapper code that marshals data from one environment to another, and that translates calls from one language to the other, is an interoperability (interop) assembly, which always appears as a DLL. Fortunately, you don’t have to write this code by hand because the task is somewhat mundane. Microsoft was able to automate the process required to create an interop DLL.

Of course, Microsoft couldn’t make the decision straightforward or simple. You use different utilities for controls and components. The Type Library Import (TLbImp) utility produces a DLL suitable for component work, while the ActiveX Import (AxImp) utility produces a pair of DLLs suitable for control work. In many cases, the decision is easy — a COM component that supports a visual interface should use AxImp. However, some COM components, such as Windows Media Player (WMP.DLL) are useful as either controls or components. The example in this chapter uses the control form because that’s the way you’ll use Windows Media Player most often, but it’s important to make the decision. The following sections describe how to use both the TLbImp and AxImp utilities.

Accessing the Visual Studio .NET Utilities

You want to create an interop assembly in the folder that you’ll use for your sample application. However, you also need access to the .NET utilities. The best way to gain this access is to open a Visual Studio command prompt by choosing Start ➪ Programs ➪ Microsoft Visual Studio 2010 ➪ Visual Studio Tools ➪ Visual Studio Command Prompt (2010). If you’re working with Vista or Windows 7, right-click the Visual Studio Command Prompt (2010) entry and choose Run As Administrator from the context menu to ensure you have the rights required to use the utilities. Windows will open a command prompt that provides the required access to the .NET utilities.

Understanding the Type Library Import Utility

Remember that you always use Type Library Import (TLbImp) for components, not for controls. Before you can use TLbImp, you need to know a bit more about it. Here’s the command line syntax for the tool:

TlbImp TypeLibName [Options]

The TypeLibName argument is simply the filename of the COM component that you want to use to create an interop assembly. A COM component can have a number of file extensions, but the most common extensions are .DLL, .EXE, and .OCX.

The TypeLibName argument can specify a resource identifier when the library contains more than one resource. Simply follow the filename with a backslash and the resource number. For example, the command line TLbImp MyModule .DLL1 would create an output assembly that contains only resource 1 in the MyModule.DLL file.

You can also include one or more options that modify the behavior of TLbImp. The following list describes these options.

  • /out:FileName: Provides the name of the file you want to produce as output. If you don’t provide this argument, the default is to add Lib to the end of the filename for the type library. For example, WMP.DLL becomes WMPLib.DLL.
  • /namespace:Namespace: Defines the namespace of the classes within the interop assembly. The default is to add Lib to the filename of the type library. For example, if the file has a name of WMP.DLL, the namespace is WMPLib.
  • /asmversion:Version: Specifies the file version number of the output assembly. This information appears on the Version tab of the file Properties dialog box shown in Figure 9-5. The default version number is

You must specify a version number using dotted syntax. The four version number elements are: major version, minor version, build number, and revision number. For example, would specify a major version number of 1, minor version number of 2, a build number of 3, and a revision number of 4.

  • /reference:FileName: Determines the name of the assembly that TLbImp uses to resolve references. There’s no default value. You may use this command line switch as many times as needed to provide a complete list of assemblies.
  • /tlbreference:FileName: Determines the name of the type library that TLbImp uses to resolve references. There’s no default value. You may use this command line switch as many times as needed to provide a complete list of assemblies.
  • /publickey:FileName: Specifies the name of a file containing a strong name public key used to sign the assembly. There’s no default value.
  • /keyfile:FileName: Specifies the name of a file containing a strong name key pair used to sign the assembly. There’s no default value.
  • /keycontainer:FileName: Specifies the name of a key container containing a strong name key pair used to sign the assembly. There’s no default value.
  • /delaysign: Sets the assembly to force a delay in signing. Use this option when you want to use the assembly for experimentation only.
Include version information for the assembly so others know about it.
Fi gure 9-5: Include version information for the assembly so others know about it.
  • /product:Product: Defines the name of the product that contains this assembly. This information appears on the Version tab of the file Properties dialog box shown in Figure 9-5. The default is to say that the assembly is imported from a specific type library.
  • /productversion:Version: Defines the product version number of the output assembly. This information appears on the Version tab of the file Properties dialog box shown in Figure 9-5. The default version number is
  • /company:Company: Defines the name of the company that produced the output assembly. This information appears on the Version tab of the file Properties dialog box shown in Figure 9-5. There’s no default value.
  • /copyright:Copyright: Defines the copyright information that applies to the output assembly. This information appears on the Version tab of the file Properties dialog box shown in Figure 9-5. There’s no default value.
  • /trademark:Trademark: Defines the trademark and registered trademark information that applies to the output assembly. This information appears on the Version tab of the file Properties dialog box shown in Figure 9-5. There’s no default value.
  • /unsafe: Creates an output assembly that lacks runtime security checks. Using this option will make the assembly execute faster and reduce its size. However, you shouldn’t use this option for production systems because it does reduce the security features that the assembly would normally possess.
  • /noclassmembers: Creates an output assembly that has classes, but the classes have no members.
  • /nologo: Prevents the TLbImp utility from displaying a logo when it starts execution. This option is useful when performing batch processing.
  • /silent: Prevents the TLbImp utility from displaying any output, except error information. This option is useful when performing batch processing.
  • /silence:WarningNumber: Prevents the TLbImp utility from displaying output for the specified warning number. This option is useful when an assembly contains a number of warnings that you already know about and you want to see only the warnings that you don’t know about. You can’t use this option with the /silent command line switch.
  • /verbose: Tells the TLbImp utility to display every available piece of information about the process used to create the output assembly. This option is useful when you need to verify the assembly before placing it in a production environment or when you suspect a subtle error is causing application problems (or you’re simply curious).
  • /primary: Creates a Primary Interop Assembly (PIO). A COM component may use only one PIO and you must sign the PIO (use the /publickey, /keyfile, or /keycontainer switches to sign the assembly). See for additional information.
  • /sysarray: Specifies that the assembly should use SAFEARRAY in place of the standard System.Array.
  • /machine:MachineType: Creates an assembly for the specified machine type. The valid inputs for this command line switch are:
    • X86
    • X64
    • Itanium
    • Agnostic
  • /transform:TransformName: Performs the specified transformations on the assembly. You may use any of these values as a transformation.
    • SerializableValueClasses: Forces TLbImp to mark all of the classes as serializable.
    • DispRet: Applies the [out, retval] attribute to methods that have a dispatch-only interface.
  • /strictref: Forces TLbImp to use only the assemblies that you specify using the /reference command line switch, along with PIAs, to produce the output assembly, even if the source file contains other references. The output assembly might not work properly when you use this option.
  • /strictref:nopia: Forces TLbImp to use only the assemblies that you specify using the /reference command line switch to produce the output assembly, even if the source file contains other references. This command line switch ignores PIAs. The output assembly might not work properly when you use this option.
  • /VariantBoolFieldToBool: Converts all VARIANT_BOOL fields in structures to bool.
  • /? or /help: Displays a help message containing a list of command line options for the version of TLbImp that you’re using.

Understanding the ActiveX Import Utility

The example in this chapter relies on the ActiveX Import (AxImp) utility because it produces the files you need to create a control (with a visual interface) rather than a component. When you use this utility, you obtain two files as output. The first contains the same information you receive when using the TLbImp utility. The second, the one with the Ax prefix, contains the code for a control. Before you can use AxImp, you need to know a bit more about it. Here’s the command line syntax for the tool:

AxImp OcxName [Options]

The OcxName argument is simply the filename of the COM component that you want to use to create a control version of an interop assembly. A COM component can have a number of file extensions, but the most common extensions are .DLL, .EXE, and .OCX. It’s uncommon for an OLE Control eXtension (OCX), a COM component with a visual interface, to have a .EXE file extension.

You can also include one or more options that modify the behavior of AxImp. The following list describes these options.

  • /out:FileName: Provides the name of the ActiveX library file you want to produce as output. If you don’t provide this argument, the default is to add Lib to the end of the filename for the type library. For example, WMP.DLL becomes WMPLib.DLL and AxWMPLib.DLL. Using this command line switch changes the name of the AxWMPLib.DLL file. For example, if you type AxImp WMP .DLL /out:WMPOut.DLL and press Enter, the utility now outputs WMPLib.DLL and WMPOut.DLL.
  • /publickey:FileName: Specifies the name of a file containing a strong name public key used to sign the assembly. There’s no default value.
  • /keyfile:FileName: Specifies the name of a file containing a strong name key pair used to sign the assembly. There’s no default value.
  • /keycontainer:FileName: Specifies the name of a key container containing a strong name key pair used to sign the assembly. There’s no default value.
  • /delaysign: Sets the assembly to force a delay in signing. Use this option when you want to use the assembly for experimentation only.
  • /source: Generates the C# source code for a Windows Forms wrapper. You don’t need to use this option when working in IronPython because the code doesn’t show how to use the wrapper — it simply shows the wrapper code itself.
  • /rcw:FileName: Specifies an assembly to use for Runtime Callable Wrapper (RCW) rather than generating a new one. In most cases, you want to generate a new RCW when working with IronPython.
  • /nologo: Prevents the AxImp utility from displaying a logo when it starts execution. This option is useful when performing batch processing.
  • /silent: Prevents the AxImp utility from displaying any output, except error information. This option is useful when performing batch processing.
  • /verbose: Tells the AxImp utility to display every available piece of information about the process used to create the output assembly. This option is useful when you need to verify the assembly before placing it in a production environment or when you suspect a subtle error is causing application problems (or you’re simply curious).
  • /? or /help: Displays a help message containing a list of command line options for the version of AxImp that you’re using.

Creating the Windows Media Player Interop DLL

Now that you have an idea of how to use the AxImp utility, it’s time to see the utility in action. The following command line creates an interop assembly for the Windows Media Player.

AxImp %SystemRoot%System32WMP.DLL

This command line switch doesn’t specify any options. It does include %SystemRoot%, which points to the Windows directory on your machine (making it possible to use the command line on more than one system, even if those systems have slightly different configurations). When you execute this command line, you see the AxImp utility logo. After a few minutes work, you’ll see one or more warning or error messages if the AxImp utility encounters problems. Eventually, you see a success message, as shown in Figure 9-6.

The AxImp tells you that it has generated the two DLLs needed for a control.
Fi gure 9-6: The AxImp tells you that it has generated the two DLLs needed for a control.

Exploring the Windows Media Player Interop DLL

When working with imported Python modules, you use the dir() function to see what those modules contain. In fact, you often use dir() when working with .NET assemblies as well, even though you have the MSDN documentation at hand. Theoretically, you can also use dir() when working with imported COM components as well, but things turn quite messy when you do. The “Using the Windows Media Player Interop DLL” section of this chapter describes how to import and use an interop assembly, but for now, let’s just look at WMPLib.DLL using dir(). Figure 9-7 shows typical results.

Using dir() won’t work well with interop assemblies in many cases.
Fi gure 9-7: Using dir() won’t work well with interop assemblies in many cases.

The list goes on and on. Unfortunately, this is only the top level. You still need to drill down into the interop assembly, so things can become confusing and complex. Figuring out what you want to use is nearly impossible. Making things worse is the fact that any documentation you obtain for the interop assembly probably won’t work because the documentation will take the COM perspective of working with the classes and you need the IronPython perspective. Using dir() won’t be very helpful in this situation.

Fortunately, you have another alternative in the form of the Intermediate Language Disassembler (ILDasm) utility. This utility looks into the interop assembly and creates a graphic picture of it for you. Using this utility, you can easily drill down into the interop assembly and, with the help of the COM documentation, normally figure out how to work with the COM component — even complex COM components such as the Windows Media Player.

To gain access to ILDasm, you use the same process you use for TLbImp to create a Visual Studio Command Prompt. At the command prompt, type ILDasm WMPLib.DLL and press Enter (see more of the command line options in the “Using the ILDasm Command Line” section of the chapter). The ILDasm utility will start and show entries similar to those shown in Figure 9-8.

ILDasm is an important tool for the IronPython developer who wants to work with COM. With this in mind, the following sections provide a good overview of ILDasm and many of its usage details. Most important, these sections describe how to delve into the innermost parts of any interop assembly.

Use ILDASM to explore WMPLib.DLL.
Fi gure 9-8: Use ILDASM to explore WMPLib.DLL.

Using the ILDasm Command Line

The ILDasm utility usually works fine when you run it and provide the filename of the interop assembly you want to view. However, sometimes an interop assembly is so complex that you really do want to optimize the ILDasm view. Consequently, you use command line options to change the way ILDasm works. ILDasm has the following command line syntax.

ildasm [options] <file_name> [options]

Even though this section shows the full name of all the command line switches, you can use just the first three letters. For example, you can abbreviate /BYTES as /BYT. In addition, ILDasm accepts both the dash (-) and slash (/) as command line switch prefixes, so /BYTES and -BYTES work equally well.

The options can appear either before or after the filename. You can divide the options into those that affect output redirection (sending the output to a location other than the display) and those that change the way the file/console output appears. ILDasm further divides the file/console options into those that work with EXE and DLL files, and those that work with EXE, DLL, OBJ, and LIB files. Here are the options for output redirection.

  • /OUT=Filename: Redirects the output to the specified file rather than to a GUI.
  • /TEXT: Redirects the output to a console window rather than to a GUI. This option isn’t very useful for anything but the smallest files because the entire content of the interop assembly simply scrolls by. Of course, you can always use a pipe (|) to send the output to the More utility to view the output one page at a time.
  • /HTML: Creates the file in HTML format (valid with the /OUT option only). This option is handy for making the ILDasm available for a group of developers on a Web site. For example, if you type ILDasm /OUT=WMPLib.HTML /HTML WMPLib.DLL and press Enter, you obtain WMPLib.HTML. The resulting file is huge — 7.53 MB for WMPLib.HTML. Figure 9-9 shows how this file will appear.
  • /RTF: Creates the file in RTF format (valid with the /OUT option only). This option is handy for making the ILDasm available for a group of developers on a local network using an application such as Word. For example, if you type ILDasm /OUT=WMPLib.RTF /RTF WMPLib.DLL and press Enter, you obtain WMPLib.RTF. The resulting file is huge — 5.2 MB for WMPLib.RTF, and may cause Word to freeze.

Of course, you might not want to redirect the output to a file, but may want to change the way the console appears instead. The following options change the GUI or file/console output for EXE and DLL files only.

  • /BYTES: Displays actual bytes (in hex) as instruction comments. Generally, this information isn’t useful unless you want to get into the low-level details of the interop assembly. For example, you might see a series of hex bytes such as // SIG: 20 01 01 08, which won’t be helpful to most developers. (In this case, you’re looking at the signature for the WMPLib .IAppDispatch.adjustLeft() method.)
HTML output is useful for viewing ILDasm output in a browser
Fi gure 9-9: HTML output is useful for viewing ILDasm output in a browser
  • /RAWEH: Shows the exception handling clauses in raw form. This isn’t a useful command line switch for interop assemblies because interop assemblies don’t require exception handlers in most cases.
  • /TOKENS: Displays the metadata tokens of classes and members as comments in the source code, as shown in Figure 9-10 for the WMPLib.IAppDispatch.adjustLeft() method. For example, the metadata token for mscorlib is /*23000001*/. Most developers won’t require this information.
The metadata tokens appear as comments beside the coded text.
Fi gure 9-10: The metadata tokens appear as comments beside the coded text.
  • /SOURCE: Shows the original source lines as comments when available. Unfortunately, when working with an interop assembly, there aren’t any original source lines to show, so you won’t need to use this command line switch.
  • /LINENUM: Shows the original source code line numbers as comments when available. Again, when working with an interop assembly, there aren’t any original source code line numbers to show so you won’t need to use this command line switch.
  • /VISIBILITY=Vis[+Vis…]: Outputs only the items with specified visibility. The valid inputs for this argument are:
    • PUB: Public
    • PRI: Private
    • FAM: Family
    • ASM: Assembly
    • FAA: Family and assembly
    • FOA: Family or assembly
    • PSC: Private scope
  • /PUBONLY: Outputs only the items with public visibility (same as /VIS=PUB).
  • /QUOTEALLNAMES: Places single quotes around all names. For example, instead of seeing mscorlib, you’d see ‘mscorlib‘. In some cases, using this approach makes it easier to see or find specific names in the code.
  • /NOCA: Suppresses the output of custom attributes.
  • /CAVERBAL: Displays all of the Custom Attribute (CA) blobs in verbal form. The default setting outputs the CA blobs in binary form. Using this command line switch can make the code more readable, but also makes it more verbose (larger).
  • /NOBAR: Tells ILDasm not to display the progress bar as it redirects the interop assembly output to another location (such as a file).

ILDasm includes a number of command line switches that affect file and console output only. The following command line switches work for EXE and DLL files.

  • /UTF8: Forces ILDasm to use UTF-8 encoding for output in place of the default ANSI encoding.
  • /UNICODE: Forces ILDasm to use Unicode encoding for output in place of the default ANSI encoding.
  • /NOIL: Suppresses Intermediate Language (IL) assembler code output. Unfortunately, this option isn’t particularly useful because it creates a file that contains just the disassembly comments, not any of the class or method information. You do get the resource (.RES) file containing the resource information for the interop assembly (such as the version number). To use this command line switch, you must include redirection such as ILDasm /OUT=WMPLib.HTML / HTML /NOIL WMPLib.DLL to produce WMPLib.HTML as output.
  • /FORWARD: Forces ILDasm to use forward class declaration. In some cases, this command line switch can reduce the size of the disassembly.
  • /TYPELIST: Outputs a full list of types. Using this command line switch can help preserve type ordering.
  • /HEADERS: Outputs the file header information in the output.
  • /ITEM=Class[::Method[(Signature)]]: Disassembles only the specified item. Using this command line switch can greatly reduce the confusion of looking over an entire interop assembly.
  • /STATS: Provides statistical information about the image. The statistics appear at the beginning of the file in comments. Here’s a small segment of the statistics you might see (telling you about the use of space in the file).
    // File size : 331776
    // PE header size : 4096 (496 used) ( 1.23%)
    // PE additional info : 1015 ( 0.31%)
    // Num.of PE sections : 3
    // CLR header size : 72 ( 0.02%)
    // CLR meta-data size : 256668 (77.36%)
    // CLR additional info : 0 ( 0.00%)
    // CLR method headers : 9086 ( 2.74%)
    // Managed code : 51182 (15.43%)
    // Data : 8192 ( 2.47%)
    // Unaccounted : 1465 ( 0.44%)
  • /CLASSLIST: Outputs a list of the classes defined in the module. The class list appears as a series of comments at the beginning of the file. Here’s an example of the class list output for WMPLib.DLL
    // Classes defined in this module:
    // Interface IWMPEvents (public) (abstract) (auto) (ansi) (import)
    // Class WMPPlaylistChangeEventType (public) (auto) (ansi) (sealed)
    // Interface IWMPEvents2 (public) (abstract) (auto) (ansi) (import)
    // Interface IWMPSyncDevice (public) (abstract) (auto) (ansi) (import)
    // Class WMPDeviceStatus (public) (auto) (ansi) (sealed)
    // Class WMPSyncState (public) (auto) (ansi) (sealed)
    // Interface IWMPEvents3 (public) (abstract) (auto) (ansi) (import)
    // Interface IWMPCdromRip (public) (abstract) (auto) (ansi) (import)
  • /ALL: Performs the combination of the /HEADER, /BYTES, /STATS, /CLASSLIST, and /TOKENS command line switches.

This set of command line switches also affects just file and console output. However, you can use them for EXE, DLL, OBJ, and LIB files.

  • /METADATA[=Specifier]: Shows the interop assembly metadata for the elements defined by Specifier. Here are the values you can use for Specifier.
    • MDHEADER: MetaData header information and sizes
    • HEX: More data in hex as well as words
    • CSV: Record counts and heap sizes
    • UNREX: Unresolved externals
    • SCHEMA: MetaData header and schema information
    • RAW: Raw MetaData tables
    • HEAPS: Raw heaps
    • VALIDATE: MetaData consistency validation

The final set of command line switches affects file and console output for LIB files only.

  • /OBJECTFILE=Obj_Filename: Shows the MetaData of a single object file in library.

Working with ILDasm Symbols

When working with ILDasm, you see a number of special symbols. Unfortunately, the utility often leaves you wondering what the symbols mean. Here are some of the most common symbols you encounter when working with COM components.

  • Interface: Represents an interface with which you can interact.
  • Private Class: Represents an abstract or sealed class in most cases.
  • Enumeration: Contains a list of enumerated items you use to provide values for method calls and other tasks.
  • Attribute: Provides access to the attributes that describe a COM component. Common attributes and attribute containers include:
    • Manifest (and its associated attributes)
    • Extends (defines a class that the class extends)
    • Implements (defines an interface that the class implements)
    • ClassInterface (see .runtime.interopservices.classinterfaceattribute.aspx for details)
    • GuidAttribute (see .runtime.interopservices.guidattribute.aspx for details)
    • TypeLibTypeAttribute (see system.runtime.interopservices.typelibtypeattribute.aspx for details)
    • InterfaceTypeAttribute (see system.runtime.interopservices.interfacetypeattribute.aspx for details)
  • Method: Describes a method that you can use within an interface or private class.
  • Property: Describes a property that you can use within an interface or private class.
  • Variable: Defines a variable of some type within an interface or private class. The variable could be an interface, such as IConnectionPoint, or an array, such as ArrayList, or anything else that the developer wanted to include.
  • Event: Specifies an event that occurs within the interface or private class.

Exploring ILDasm entries

It’s important to remember that interop assemblies simply provide a reference to the actual code found in the COM component. Even so, you can use ILDasm to find out all kinds of interesting information about the component. At the top level, you can see a list of all of the interfaces, classes, and enumerations, as shown in Figure 9-8. The next level is to drill down into specific methods and properties, as shown in Figure 9-11.

Opening an interface displays all the methods it contains.
Fi gure 9-11: Opening an interface displays all the methods it contains.

The information shown in this figure is actually the most valuable information that ILDasm provides because you can use it to discover the names of methods and properties you want to use in your application. In addition, these entries often provide clues about where to look for additional information in the vendor help files. Sometimes these help files are a little disorganized and you might not understand how methods are related until you see this visual presentation of them.

It’s possible to explore the interop assembly at one more level. Double-click any of the methods, properties, or attributes and you’ll see a dialog box like the one shown in Figure 9-12. The amount of information you receive may seem paltry at first. However, look closer and you’ll discover that this display often tells you about calling requirements. For example, you can discover the data types you need to rely on to work with the COM component (something that COM documentation can’t tell you because the vendor doesn’t know that you’re using the component from .NET).

Discover the calling requirements for methods by reviewing the methods’ underlying code.
Fi gure 9-12: Discover the calling requirements for methods by reviewing the methods’ underlying code.

Using the Windows Media Player Interop DLL

It’s finally time to use early binding to create a connection to the Windows Media Player. This example uses the Windows Media Player as a control. You might find a number of online sources that say it’s impossible to use the Windows Media Player as a control, but it’s actually quite doable. Of course, you need assistance from yet another one of Microsoft’s handy utilities, Resource Generator (ResGen) to do it. The example itself relies on the normal combination of a form file and associated application file. The following sections provide everything needed to create the example.

Working with ResGen

Whenever you drop a control based on a COM component onto a Windows Forms dialog box, the IDE creates an entry for it in the .RESX file for the application. This entry contains binary data that describes the properties for the COM component. You may not know it, but most COM components have a Properties dialog box that you access by right-clicking the control and choosing Properties from the context menu. These properties are normally different from those shown in the Properties window for the managed control. Figure 9-13 shows the Properties dialog box for the Windows Media Player.

The COM component has properties that differ from the managed control.
Fi gure 9-13: The COM component has properties that differ from the managed control.

It’s essential to remember that the managed control is separate from the COM component in a Windows Forms application. The COM component properties appear in a separate location and the managed environment works with them differently. If you look in the .RESX file, you see something like this:

<data name=”MP.OcxState” mimetype=”application/”>

This binary data contains the information needed to configure the COM aspects of the component. When the application creates the form, the binary data is added to the component using the OcxState property like this:

this.MP.OcxState =

Because of the managed code/COM component duality of a Windows Forms application, you can’t simply embed the COM component into an IronPython application using techniques such as the one shown at You must provide the binary data to the COM component using the OcxState property. Unfortunately, IronPython developers have an added twist to consider. The C# code shown previously won’t work because you don’t have access to a ComponentResourceManager for the IronPython form. Instead, you must read the resource from disk using code like this

self.resources = System.ComponentModel.ComponentResourceManager.
‘frmUseWMP’, ‘C:/0255 – Source Code/Chapter09’, None)

Now, here’s where the tricky part begins (you might have thought we were there already, but we weren’t). The CreateFileBasedResourceManager() method doesn’t support .RESX files. Instead, it supports .RESOURCES files. The ResGen utility can create .RESOURCES files. You might be tempted to think that you can duplicate the binary data from the .RESX file using .TXT files as suggested by the ResGen documentation. Unfortunately, .TXT files can only help you create string data in .RESOURCES files.

So your first step is to create a Windows Forms application, add the component to it, perform any required COM component configuration (no need to perform the managed part), save the result, and then take the resulting .RESX file for your IronPython application. You can then use ResGen to create the .RESOURCES file using a command line like this:

ResGen frmUseWMP.RESX

ResGen outputs a .RESOURCES file you can use within your application. Of course, like every Microsoft utility, ResGen offers a little more than simple conversion. Here’s the command line syntax for ResGen:

ResGen inputFile.ext [outputFile.ext] [/str:lang[,namespace[,class[,file]]]]
ResGen [options] /compile inputFile1.ext[,outputFile1.resources] […]

Here are the options you can use.

  • /compile: Performs a bulk conversion of files from one format to another format. Typically, you use this feature with a response file where you provide a list of files to convert.
  • /str:language[, namespace[, classname[, filename]]]: Defines a strongly typed resource class using the specified programming language that relies on Code Document Object Model (CodeDOM) (see for details). To ensure that the strongly typed resource class works properly, the name of your output file, without the .RESOURCES extension, must match the [namespace.]classname of your strongly typed resource class. You may need to rename your output file before using it or embedding it into an assembly.
  • /useSourcePath: Specifies that ResGen uses each source file’s directory as the current directory for resolving relative file paths.
  • /publicClass: Creates the strongly typed resource class as a public class. You must use this command line switch with the /str command line switch.
  • /r:assembly: Tells ResGen to load types from the assemblies that you specify. A .RESX file automatically uses newer assembly types when you specify this command line switch. You can’t form the .RESX file to rely on older assembly types.
  • /define:A[,B]: Provides a means for performing optional conversions specified by #ifdef structures within a .RESTEXT (text) file.
  • @file: Specifies the name of a response file to use for additional command line options. You can only provide one response file for any given session.

Creating the Media Player Form Code

As normal, the example relies on two files to hold the form and the client code. Because we’re using a COM component for this example, the form requires a number of special configuration steps. Listing 9-1 shows the form code.

Listin g 9-1: Creating a Windows Forms application with a COM component

# Set up the path to the .NET Framework.
import sys
# Make clr accessible.
import clr
# Add any required references.
# Import the .NET assemblies.
import System
import System.Windows.Forms
import System.Drawing.Point
import AxWMPLib
class frmUseWMP(System.Windows.Forms.Form):
# This function performs all of the required initialization.
def InitializeComponent(self):
# Create a Component Resource Manager
self.resources = System.ComponentModel.ComponentResourceManager.
‘frmUseWMP’, ‘C:/0255 – Source Code/Chapter09’, None)
# Configure Windows Media Player
self.MP = AxWMPLib.AxWindowsMediaPlayer()
self.MP.Dock = System.Windows.Forms.DockStyle.Fill
self.MP.Enabled = True
self.MP.Location = System.Drawing.Point(0, 0)
self.MP.Name = “MP”
self.MP.Size = System.Drawing.Size(292, 266)
self.MP.OcxState = self.resources.GetObject(“MP.OcxState”)
# Configure the form.
self.ClientSize = System.Drawing.Size(350, 200)
self.Text = ‘Simple Windows Media Player Example’
# Add the controls to the form.

The code begins with the normal steps of adding the .NET Framework path, making clr accessible, importing the required DLLs, and importing the required assemblies. Notice that the example uses the AxWMPLib.DLL file and AxWMPLib assembly. Remember that the Ax versions of the files provide wrapping around the ActiveX controls to make them usable as a managed control.

The code begins by creating a ComponentResourceManager from a file, using the CreateFileBasedResourceManager() method. Normally, a managed application would create the ComponentResourceManager directly from the data stored as part of the form. This is a special step for IronPython that could cause you grief later if you forget about it.

Even though Listing 9-1 shows the CreateFileBasedResourceManager() method call on multiple lines, it appears on a single line in the actual source code. The IronPython call won’t work if you place it on multiple lines because IronPython lacks a line continuation character (or methodology).

Media Player (MP) configuration comes next. You must instantiate the control from the AxWMPLib .AxWindowsMediaPlayer() constructor, rather than using the COM component constructor. The Ax constructor provides a wrapper with additional features you need within the Windows Forms environment. Like most controls, you need to specify control position and size on the form. However, because of the nature of the Windows Media Player, you want it to fill the client area of the form, so you set the Dock property to System.Windows.Forms.DockStyle.Fill.

The one configuration item that you must perform correctly is setting the COM component values using the MP.OcxState property. The ComponentResourceManager, resources, contains this value. You simply set the MP.OcxState property to resources.GetObject(“MP.OcxState”) — this technique is also different from what you’d use in a C# or Visual Basic.NET application. The rest of the form code isn’t anything special — you’ve seen it in all of the Windows Forms examples so far.

Creating the Media Player Application Code

Some COM components require a lot of tinkering by the host application, despite being self-contained for the most part. However, the Windows Media Player is an exception to the rule. Normally, you want to tinker with it as little as possible to meet your programming requirements. In some cases, you won’t want to tinker at all, as shown in Listing 9-2.

Listin g 9-2: Interacting with the COM component

# Set up the path to the .NET Framework.
import sys
# Make clr accessible.
import clr
# Add any required references.
# Import the .NET assemblies.
import System
import System.Windows.Forms
# import the form.
from frmUseWMP import *
# Define the Windows Form and the elements of this specific instance.
WMPForm = frmUseWMP()
# Run the application.

This code does the minimum possible for a Windows Forms application. It contains no event handlers or anything of that nature. In fact, the code simply displays the forms. Believe it or not, the actual settings for the application appear as part of the .RESOURCES file. What you see when you run this application appears in Figure 9-14.

This is a fully functional Windows Media Player. You can adjust the volume, set the starting position, pause the play, or do anything else you normally do with the Windows Media Player. It’s even possible to right-click the Windows Media Player to see the standard context menu. The context menu contains options to do things like slow the play time, see properties, and change options. Play with the example a bit to see just how fully functional it is.

The example application shows a form with Windows Media Player on it.
Figure 9-14: The example application shows a form with Windows Media Player on it.

A Quick View of the Windows Media Player Component Form

You may encounter times when you really don’t want to display the Windows Media Player as a control — you simply want it to work in the background. In this case, you can use the Windows Media Player as a component. The following code snippet shows the fastest way to perform this task in IronPython (the sys.path.append() call should appear on a single line, even though it appears on two lines in the book). (You can find the entire source in the MPComponent example supplied with the book’s source code.)

# Set up the path to the .NET Framework.
import sys
# Make clr accessible.
import clr
# Add any required references.
# Import the .NET assemblies.
import System
import System.Windows.Forms
import WMPLib
# import the form.
from frmMPComponent import *
# Define the event handlers.
def btnPlay_Click(*args):
# Create the Media Player object.
MP = WMPLib.WindowsMediaPlayerClass()
# Assign the media player event.
MP.MediaError += PlayerError
# Assign a sound to the Media Player.
MP.URL = “Bells.WAV”
# Play the sound.

Notice that you start by adding a reference to WMPLib.DLL and importing WMPLib into IronPython, rather than using the Ax versions. The next step appears in the btnPlay_Click() event handler. After the code imports the required support, it instantiates an object (MP) of the WindowsMediaPlayerClass, not WindowsMediaPlayer (an interface) as many of the Microsoft examples show.

Now you can perform various tasks with the resulting component. The example is simple. All it does is assign a filename to the URL property, and then call on to play the file. You can find additional information on using this technique at

Performing Late Binding Using Activator.CreateInstance()

The Activator.CreateInstance() method is one of the more powerful ways to work with objects of all kinds. In fact, this particular method can give your IronPython applications the same kind of support as the Windows scripting engines CScript and WScript.

When working with the Activator.CreateInstance() method, you describe the type of object you want to create. The object can be anything. In fact, if you look through the HKEY_CLASSES_ ROOT hive of the registry, you’ll find a number of objects to try on your system.

The example in this section does something a bit mundane, but also interesting — it demonstrates how to interact with the Shell objects. You can get a description of the Shell objects at http:// The main reason to look at the Shell objects is that every Windows machine has them and they’re pretty useful for detecting user preferences. Listing 9-3 shows the code used for this example.

Listin g 9-3: Working with Shell objects

# We only need the System assembly for this example.
from System import Activator, Type
# Import the time module to help with a pause.
import time
# Constants used for Shell settings.
from ShellSettings import *
# Create the Shell object.
ShObj = Activator.CreateInstance(Type.GetTypeFromProgID(‘Shell.Application’))
# Toggle the Desktop.
raw_input(‘Press Enter to show and then hide the Desktop’)
# Show some of the settings.
print ‘nThe user wants to show file extensions:’,
print ShObj.GetSetting(SSF_SHOWEXTENSIONS)
print ‘The user wants to see system files:’,
print ShObj.GetSetting(SSF_SHOWSYSFILES)
print ‘The user also wants to see operating system files:’,
# Check Explorer policies.
print ‘nThe NoDriveTypeAutoRun policies are:’
# Obtain the bit values. These values are:
# 0 Unknown drives
# 1 No root directory
# 2 Removable drives (Floppy, ZIP)
# 3 Hard disk drives
# 4 Network drives
# 5 CD-ROM drives
# 6 RAM disk drives
# 7 Reserved
MyBits = ShObj.ExplorerPolicy(‘NoDriveTypeAutoRun’)
# Display the results.
if MyBits.__and__(0x01) == 0x01:
print(‘tAutorun Disabled for Unknown Drives’)
print(‘tAutorun Enabled for Unknown Drives’)
if MyBits.__and__(0x02) == 0x02:
print(‘tAutorun Disabled for No Root Directory’)
print(‘tAutorun Enabled for No Root Drives’)
if MyBits.__and__(0x04) == 0x04:
print(‘tAutorun Disabled for Removable (Floppy/ZIP) Drives’)
print(‘tAutorun Enabled for Removable (Floppy/ZIP) Drives’)
if MyBits.__and__(0x08) == 0x08:
print(‘tAutorun Disabled for Hard Disk Drives’)
print(‘tAutorun Enabled for Hard Disk Drives’)
if MyBits.__and__(0x10) == 0x10:
print(‘tAutorun Disabled for Network Drives’)
print(‘tAutorun Enabled for Network Drives’)
if MyBits.__and__(0x20) == 0x20:
print(‘tAutorun Disabled for CD-ROM Drives’)
print(‘tAutorun Enabled for CD-ROM Drives’)
if MyBits.__and__(0x40) == 0x40:
print(‘tAutorun Disabled for RAM Disk Drives’)
print(‘tAutorun Enabled for RAM Disk Drives’)
# Pause after the debug session.
raw_input(‘Press any key to continue…’)

This example starts by showing a different kind of import call. In this case, the import retrieves only the Activator and Type classes from the System assembly. Using this approach reduces environmental clutter. In addition, using this technique reduces the memory requirements for your application and could mean the application runs faster. The example also imports the time module.

The first step in this application can seem a little complicated so it pays to break it down into two pieces. First, you must get the type of a particular object by using its identifier within the registry with the Type.GetTypeFromProgID() method. As previously mentioned, the object used in this example is Shell.Application. After the code obtains the type, it can create an instance of the object using Activator.CreateInstance().

The Shell.Application object, ShObj, provides several interesting methods and this example works with three of them. The first method, ToggleDesktop(), provides the same service as clicking the Show Desktop icon in the Quick Launch toolbar. Calling ToggleDesktop() the first time shows the desktop, while the second call restores the application windows to their former appearance. Notice the call to time.sleep(2), which provides a 2-second pause between the two calls.

The second method, GetSetting(), accepts a constant value as input. Listing 9-4 shows common settings you can query using GetSetting(). The example shows the results of three queries about Windows Explorer settings for file display. You can see these results (as well as the results for the third method) in Figure 9-15.

Listin g 9-4: Queryable information for GetSetting()

SSF_SORTCOLUMNS = 0x00000010
SSF_DESKTOPHTML = 0x00000200
SSF_WIN95CLASSIC = 0x00000400
SSF_SHOWINFOTIP = 0x00002000
SSF_HIDEICONS = 0x00004000
SSF_FILTER = 0x00010000
SSF_WEBVIEW = 0x00020000
SSF_SEPPROCESS = 0x00080000

The shell objects provide access to all sorts of useful information.
Fi gure 9-15: The shell objects provide access to all sorts of useful information.

The third method, ExplorerPolicy(), is a registry-based query that relies on bit positions to define a value. You find these values in the HKEY_CURRENT_USERSoftwareMicrosoft WindowsCurrentVersionPoliciesExplorer registry key. The two most common policies are NoDriveAutorun and NoDriveTypeAutoRun. When working with the NoDriveAutorun policy, Windows enables or disables autorun on a drive letter basis where bit 0 is drive A and bit 25 is drive Z. Listing 9-3 shows how to work with the bits for the NoDriveTypeAutoRun policy, while Figure 9-15 shows the results for the host machine.

You can find a number of other examples of this kind of late binding for IronPython on the Internet. For example, you can see a Word late binding example at .php/Extremely_Late_Binding. This particular example would possibly be the next step for many developers in working with Activator.CreateInstance(). The important thing to remember is that this method is extremely flexible and that you need to think of the impossible, as well as the possible, when using it.

Performing Late Binding Using Marshal.GetActiveObject()

Sometimes you need to interact with an application that’s already running. In this case, you don’t want to create a new object; you want to gain access to an existing object. The technique used to perform this type of late binding is to call Marshal.GetActiveObject() with the type of object you want to access. Typically, you use this technique with application objects, such as a running copy of Word. Listing 9-5 shows an example of how to use Marshal.GetActiveObject() to gain access to a running Word application.

Listin g 9-5: Working with a running copy of Word

# Import only the required classes from System.
from System.Runtime.InteropServices import Marshal
# Obtain a pointer to the running Word application.
# Word must be running or this call will fail.
WordObj = Marshal.GetActiveObject(‘Word.Application’)
# Add a new document to the running copy of Word.
MyDoc = WordObj.Documents.Add()
# Get the Application object.
App = MyDoc.Application
# Type some text in the document.
App.Selection.TypeText(‘Hello World’)

The import statement differs from normal in this example. Notice that you can drill down into the namespace or class you want, and then import just the class you need. In this case, the example requires only the Marshal class from System.Runtime.InteropServices.

The first step is to get the running application. You must have a copy of Word running for this step to work; otherwise, you get an error. The call to Marshal.GetActiveObject() with Word.Application returns a Word object, WordObj. This object is the same object you get when working with Visual Basic for Applications (VBA). In fact, if you can do it with VBA, you can do it with IronPython.

After gaining access to Word, the application adds a new document using WordObj.Documents.Add(). It then creates an Application object, App. Using the App.Selection.TypeText() method, the application types some text into Word, as shown in Figure 9-16. Of course, you can perform any task required — the example does something simple for demonstration purposes.

 You can control Word using IronPython as easily as you can using VBA.
Fi gure 9-16: You can control Word using IronPython as easily as you can using VBA.


Debugging Windows Phone 7 Applications

If you are working in Visual Studio or Visual Studio Express, you can use the standard debugging tools to break, step through, and profile a Windows Phone 7 application. You can also view variable values and the execution tree and processes.

A Windows Phone 7 application uses Silverlight and Windows Presentation Foundation (WPF) to define the interfaces, so any debugging techniques you use in Silverlight and WPF also apply to Windows Phone 7. For example, there are some specific issues related to WPF styling and data binding that can arise in an application. These include the following:

  • Errors in the auto-generated partial class for a XAML component that prevent the component from being available to code in the page or the application. In most cases, you can  resolve this by right-clicking the XAML file in Solution Explorer and then clicking Run Custom Tool to regenerate the partialclass.
  • Errors in the XAML style definitions for components. These may occur in the App.xaml file or in other files within your application. Typically, the exception message indicates only that a COM component error has occurred and provides an HRESULT value. The simplest approach to resolving these types of errors are to minimize the surface area by temporarily removing some or all of the XAML styling definitions until the error disappears, and then reading them one by one to locate the faulty definition.
  • Data binding errors, such as using the wrong property name in a binding statement. This does not generate a run-time error, but the control property (such as the text) is not set. You can see a list of data binding errors in the Output window of Visual Studio or Visual Studio Express as the application executes. For example, you will see the following message if you specify binding to a property named City that does not exist in the data context.System.Windows.Data Error: BindingExpression path error:
    ‘City’ property not found on [your data context component
    name]. BindingExpression: Path=’City’ DataItem=’[your
    data context item]’; target element is ‘System.Windows.
    Controls.TextBlock’ (Name=’ItemText’); target property
    is ‘Text’ (type ‘System.String’).


  • Remote service access errors. If your application cannot retrieve data from a remote service, try copying the URL of the service from your code into a web browser to see if it is accessible. You can also download and install a web debugging proxy utility such as Fiddler or a similar utility to view all the HTTP(S) traffic between your application and the service. Fiddler is available from the Fiddler website (

One specific point to note when debugging Windows Phone 7 applications using the emulator is that certain actions within the phone may halt the debugger. For example, if the code opens a task or the launcher, or if it is tombstoned, execution may not continue automatically after the interruption. To continue debugging, press F5 in Visual Studio within 10 seconds of the task completing or the applications being reactivated.


An Overview of IronPython

It surprises many developers to discover that computer languages are for humans, not for computers. A computer couldn’t care less about which language you use, because it’s all bits and bytes in the end anyway. Consequently, when you decide to learn another computer language, it really does pay to know what that language will do for you, the developer. Otherwise, there really isn’t a point in making the effort.

One phrase you often hear when discussing Python (and by extension, IronPython) is “batteries included.” Python has an immense standard library that addresses everything from working with ZIP files to interacting with the file system. You’ll discover the details of working with the Standard Library in Chapter 6. For now, it’s important to know that the Standard Library has a lot to offer and you may very well be able to build many of your applications without ever thinking about the .NET Framework.

As previously mentioned, IronPython is a .NET version of the Python language. For a .NET developer, using IronPython has the advantage of letting you create extensions using .NET. In addition, you have full access to the .NET Framework (see Chapter 7 for details). You can work with IronPython and other .NET languages that you already know, which means that you can use the right tool for every job. However, IronPython has a few differences from the CPython implementation that everyone else uses, which means that you can occasionally run into some odd compatibility problems when using IronPython. As with most things in life, advantages usually come with a few disadvantages.

There are some basic reasons that you want to use IronPython (or Python for that matter). The most important reason is that IronPython is a dynamic language, which means that it performs many tasks during run time, rather than compile time. Using a dynamic language means that your code has advantages of static languages, such as Visual Basic, in that it can more easily adapt to changing environmental conditions. (You’ll discover many other dynamic language advantages as the chapter progresses.) Unfortunately, you often pay for runtime flexibility with poorer performance — there’s  always a tradeoff between flexibility and performance.

Dynamic languages provide a number of benefits such as the ability to enter several statements and execute them immediately to obtain feedback. Using a dynamic language also provides easier refactoring and code modification because you don’t have to change static definitions throughout your code. It’s even possible to call functions you haven’t implemented yet and add an implementation later in the code when it’s needed. Don’t get the idea that dynamic languages are new. In fact, dynamic languages have been around for a very long time. Examples of other dynamic languages include the following:

  • LISP (List Processing)
  • Smalltalk
  • JavaScript
  • PHP
  • Ruby
  • ColdFusion
  • Lua
  • Cobra
  • Groovy

Developers also assign a number of advantages specifically to the Python language (and IronPython’s implementation of it). Whether these features truly are advantages to you depends on your perspective and experience. Many people do agree that Python provides these features:

  • Support for the Windows, Linux/Unix, and Mac OS X platforms
  • Managed support using both Java and .NET
  • Considerable object-oriented programming (OOP) functionality that is easy to understand and use
  • The capability to look within the code — .NET developers will know this as a strong form of reflection
  • An extensive array of standard libraries
  • Full library support using hierarchical packages (a concept that is already familiar to every .NET developer)
  • Robust third-party libraries that support just about every need
  • Support for writing both extensions and modules in both C and C++
  • Support for writing extensions and modules using third-party solutions for both .NET (IronPython) and Java (Jython)
  • Modular application development
  • Error handling through exceptions (another concept familiar to any .NET developer)
  • High-level dynamic data types
  • Ease of embedding within applications as a scripting solution
  • Procedural code that is relatively easy and natural to write
  • Ease of reading and a clear syntax

All these features translate into increased developer productivity, which is something that dynamic languages as a whole supposedly provide (productivity is one of these issues that is hard to nail down and even harder to prove unless you resort to metrics such as lines of code, which prove useless when comparing languages). In addition to the great features that Python provides, IronPython provides a few of its own. The following list provides a brief overview of these features:

  • Full access to the .NET Framework
  • Usability within Silverlight applications
  • Interactive console with full dynamic compilation provided as part of the product
  • Accessibility from within a browser (see
    .aspx?title=SilverlightInteractiveSession for details)
  • Full extensibility using the .NET Framework
  • Complete source code available (see for details)

One of the negatives of working with IronPython, versus Python (in the form of CPython), is that you lose support for multiple platforms — you only have direct access to Windows. You can get around this problem using Mono (, but it isn’t a straightforward fix and many developers will find it cumbersome.  Of course, there isn’t any way to get around the lack of Java support — you simply choose one virtual machine or the other. Appendix A lists more IronPython differences from CPython, most of which will cause compatibility and other issues for you.

Don’t get the idea that IronPython is going to restrict your use of familiar technologies. You can still create a Windows Forms application and interact with COM. It’s even possible to create command line (console) applications  and work with the Internet just as you always have. What IronPython provides is another way to view problems that you must address using your applications. As with most languages, what you’re getting is another tool that lets you create  solutions in the least amount of time and with the fewest bugs.

Application Certification Requirements

To ensure the quality and usability of applications distributed through Windows Marketplace, every application must pass through a validation process after submission and before it is made available for download. The following are the core tenets of this validation process:

  • Applications must be reliable. This is reflected by the implementation of published best practices for creating reliable
  • Applications must use resources efficiently. They must execute efficiently on the phone and not have a negative impact on performance.
  • Applications must not interfere with the functionality of the phone. They must not modify settings, or they must prompt the user before changing any user preferences or the behavior of other applications.
  • Applications are free from viruses and malicious software. They must be safe for users to install and run.

In addition, applications must meet several other requirements. These include complying with the Microsoft policies for acceptable content and ensuring that localized metadata and content are accurately represented for the application’s supported geographic regions. The full set of requirements falls into four main categories: application code restrictions; run-time behavior, performance and metrics; user opt-in and privacy; and media and visual content. The following sections provide an overview of the requirements within each of these categories.

For full documentation of all the requirements, download Windows Phone 7 Application Certification Requirements from the Microsoft Download Center (

Application Code Restrictions

This section describes the requirements for your Windows Phone 7 applications in terms of the code you write, the way the application works, and the way that you compile it.

Your application must run on any Windows Phone 7 device, regardless of model, screen size, keyboard hardware, or manufacturer. The application must use only the Windows Phone Application Platform documented APIs, and it must not use PInvoke or COM interoperability. If you use controls from the System.Windows. Controls namespace, you must not call any APIs in the Microsoft. Xna.Framework.Game or Microsoft.Xna.Framework.Graphics assemblies.

The application runs in a sandbox on the device. Application code must be type-safe when compiled to Microsoft intermediate language (MSIL) code. You cannot use unsafe code or security critical code. You also cannot redistribute the Windows Phone assemblies; however, you can redistribute the Panorama, Pivot, and Map control assemblies if these are used in your application.

The application must also handle all exceptions raised by the .NET Framework, must not terminate unexpectedly or become unresponsive to user input, and it must display user-friendly error messages. A visual progress indicator must be displayed when executing time-consuming activities, such as downloading data over network connections, and you must provide an option to cancel this type of activity.

When you compile your application for distribution, you must do so using the Release or Retail configuration. It must not be compiled using the debug configuration, and it must not contain debugging symbols or output. However, you can submit an application with obfuscated code if you want.

Finally, the application must not use reflection to discover and invoke types that require security permissions. The repackaging process that takes place before distribution does not detect invoking types in this way, so the generated manifest will not request the required permissions. This will cause the application to fail at run time.

Run-time Behavior, Performance, and Metrics

To maintain a consistent user experience, the Back button must only be used for backward navigation in the application. Pressing the Back button must return the application to the previous page, or—if the user is already on the initial page—must close the application. If the current page displays a context menu or a dialog box, pressing the Back button must close the menu or dialog box and cancel the backward navigation to the previous page. The only exceptions to this are in games, where the Back button may display a context menu or dialog box, navigate to the previous menu screen, or close the menu.

The certification requirements for Windows Phone 7 applications specify both the startup performance of applications and some limitations on the use of resources. For example, the application must render the main user interface (UI) startup screen (not the splash screen) within five seconds on a typical physical device, and it must be responsive to user input within twenty seconds. The application must also complete execution in response to both the Activated and Deactivated events within ten seconds or it will be terminated by the operating system.

In addition, the application must not use more than 90 MB of RAM memory on the device unless it first queries the properties of the DeviceExtendedProperties class, and this class reports that more than 256 MB of memory is installed. The application must be able to run whether or not this extended memory is available, and it should vary its behavior only at run time to take advantage of additional memory, if required.

Your application should, as far as is appropriate, minimize its use of hardware resources, services, and device capabilities to preserve battery power. For example, it should use the location service and the push notification service only when required (which also minimizes the load on these Microsoft services).

An application in the foreground can continue to run when the phone screen is locked by setting the  PhoneApplicationService. ApplicationIdleDetectionMode property (you must prompt the user to allow this). When an application is running under a locked screen, it must minimize power usage as much as possible.

User Opt-in and Privacy

Your application must maintain user privacy. In particular, it must protect data provided by the user and must not pass any user-identifiable or personal information to another service or application unless you provide full details of how the information will be used and the user agrees to this (the opt-in approach).

If the application includes person-to-person communication such as chat features, and these features can be set up from the device, you must take steps to ascertain that the user is at least 13 years old before enabling this feature.

You must also obtain the user’s consent before your application uses the location service to identify the user’s location or if it uses the Microsoft Push Notification Service (MPNS) to send notifications to the user’s phone. For example, the application must ask the user for explicit permission to receive a toast notification before it first calls the BindtoShellToast method for the first time.

For information about the different types of notifications, see “Types of Push Notifications for Windows Phone” on MSDN (

If your application relies on the location feature and passes the location information to another application or service (such as a social community site), you must periodically remind users by displaying a message or including a visual indication on screen that location data is being sent to another service.

Users must also be able to turn off the location feature and push notifications within the application, and the application must either continue to work or present the user with a suitable message if it cannot work with the feature turned off. It must not simply fail when the feature is disabled.

An application in the foreground can continue to run when the phone screen is locked by setting the ApplicationIdleDetection Mode property. If you design your application with this capability, you must first obtain consent from the user to run in this mode and provide them with an option to disable it.

Your application must also ask users for permission before performing large downloads. Typically, this means asking for permission for data downloads greater than 50 MB that the application requires or for the use of services or communication protocols that may incur excessive communication costs.

Application Media and Visual Content

The visual appearance and content of an application must conform to a series of requirements. For example, in terms of styling, the UI must be readable and usable if the user changes the color scheme from the default white on black.

Windows Phone 7 applications and Windows Marketplace initially support localization into only English, French, Italian, German, and Spanish. However, it is likely that other languages will be added over time. All Windows Marketplace materials and application content must be correctly localized into the chosen language. For example, an application that is submitted in French must have a product description, UI text, screen shots, and icons in French. You can submit an application for multiple languages as a single package. If you submit separate language versions, each is validated and certified separately.

For information about the localization features in Windows Phone 7, see “Globalization and Localization Overview for Windows Phone” on MSDN (

Your applications must also abide by a series of restrictions on the content and links to content located elsewhere. These restrictions include the appropriate use of licensed content and trademarks; they also include limitations based on preventing illegal content such as libel and slander, threatening behavior, violence, pornography, and discrimination. There are very strict limits that prevent an application from containing content related to hate speech and defamation; the use or promotion of alcohol, tobacco, weapons, and drugs; certain adult-related content; and excessive profanity.

Finally, there are a series of restrictions that apply specifically to music-related or photo-related applications, and to advertising. These specify how users must be able to launch your application, and the types of advertising content that is acceptable. Although your applications can contain most types of advertising, they cannot, for example, promote other phone service plans or phone application marketplaces.

However, your application can play music in the background, even when its primary function is not related to music or video experiences.

Important Trends

Here are a few important trends and key takeaways to keep in mind as you build out your Facebook marketing program:

1. Be where the customers are—Especially if you are struggling with SEO and SEM efforts to drive traffic to your website, try going where your customers already are (that is, Facebook). Facebook Pages are the new website.

2. Get local—Facebook autocreating Place Pages aside, local business profiles are inevitable replacements for the Yellow Pages. People have a natural affinity for the local shops and restaurants where they spend time and will continue to “check in” to these local establishments. Brick-and-mortars can capitalize on the advantage of their physical locations to deepen customer connection and word-of-mouth impressions on friends’ News Feeds.

3. Personalize experiences across the Web—Facebook for Websites and hypertargeting capabilities are enabling
highly social and personalized experiences across the Web. When people visit your website, they will increasingly
expect the option to login with their Facebook credentials and to be able to bring their Facebook profile identity and
friends with them as they search, shop, or interact otherwise with your site.

4. Grow your company’s network—Social networks are growing. Studies suggest that although the average number of close connections is not deviating much from Dunbar’s number of 150, most people’s social networks are growing as a result of staying in touch with weak ties via Facebook. In fact, by inventing “fan relationships,” Facebook is extending the notion of weak ties to include not only people but also brands and businesses. For businesses, having a
bigger social network of fans is akin to having a bigger funnel of people to market to.

5. Recognize that customer loyalty has never been more valuable—In the Facebook Era, suddenly every customer has a voice, and what they say matters to their friends. Increasingly, friends are becoming more prominent filters and recommenders for news, information, and products, heavily influencing how decisions are made. When you win over (or lose) a customer, you could be winning over (or losing) an entire friend group.

Along the same vein, beware too of these common pitfalls:

1. Getting swindled by social media “experts”—It feels like everyone is a social media expert these days. Beware of fake opportunistic “experts” who have no track record of execution.

2. Outsourcing too much—Ben Smith, a marketing manager at Dunkin’ Brands, always warns companies against
outsourcing social media to their digital agency (probably for the same reason that most of us wouldn’t outsource the
company website). Facebook is a critical channel for keeping a pulse on the customer voice, and managing social
media well needs to become part of your corporate DNA. No one knows your business and your customers better than
you, and keeping Facebook efforts close allows you to adapt and respond quickly to real-time feedback. Exactly how much you outsource versus keep in-house will vary by organization, but many business leaders are choosing to own the overall social strategy themselves and delegate certain pieces, such as media buys and creative.

3. Hiring people to do what can be automated—Nor should you over-hire. Social media archiving and brand compliance work in particular can be extremely timeconsuming to do manually. Don’t make the mistake of turning social media into manual labor when there are plenty of ways to automate these tasks through off-the-shelf or custom-developed technology solutions.

4. Focusing only on technology—Technology is often part of the solution, but never the full solution. The hardest part about making Facebook work for business is the organizational change required. Successful programs require winning executive buy-in, properly training employees, and fostering a culture that is receptive to transparency and change.

5. Resting on your laurels—Facebook is rapidly evolving and shows no signs of slowing down. New features are
released every week, with major product changes almost every quarter. This is why companies can’t afford to drag
out RFP’s or wait for long decision cycles. By the time a decision is made, Facebook’s technology has changed. Partner with a vendor you know can keep up. Focusing too much on today’s features and requirements is dangerous because they may soon become obsolete.

How Facebook Is Changing the Online Marketing Discipline

Thanks to Facebook, the Internet is evolving from a contentcentric Information Web to a relationship-centric Social Web. A decade ago, information was at a premium. Today, it is relationships that are king.

Last decade, search marketing taught us to focus on maximizing each transaction, measured by click-through rates and conversions. Today, Facebook fan relationships encourage us to take a longer-term view. Rather than maximize for a single transaction, companies need to optimize for the lifetime of a customer relationship. It’s not about how much a customer buys today, but rather what she buys over a lifetime, together with how she influences others to (or not to) buy.

As marketers, we need to move up the marketing funnel and engage audiences sooner in the buying cycle because this
gives us an opportunity to build trust and help influence the purchase decision. In contrast, search marketing doesn’t
provide much opportunity to influence. By the time someone is searching on Google for “digital camera,” chances are high he is already pretty far along in the purchase decision. There is not much opportunity to influence beyond price, and that is not a game most of us want to be in.

Online marketing still needs to be performance-based, but instead of measuring click-through rates for a single
campaign, we can invest and analyze with a longer-term view.

In many ways, the Facebook Era is a throwback to the days before the Internet. This is especially true for brick-andmortar businesses, which have long mastered the art of instore customer connection. 1-800-FLOWERS.COM founder and CEO Jim McCann sums it up nicely in his foreword to my book, The Facebook Era:

“Past technologies helped drive down costs, improve reach, and grow the business, but in the process we lost something very important: customer connection. I have missed the direct customer dialog I had in our retail flower shops. The digital age has felt largely transactional in comparison. This is why I feel even more excited about the Facebook Era than I did about toll-free numbers or the Internet. The Social Web is about connecting with customers again, hearing their stories, sharing in their joys and sorrows and the most important moments of their lives. It’s about reopening the dialog so that businesses can put customers back in the driver’s seat and keep getting better.”

The challenge to all of us is how to replicate this customer connection through the online medium. Fortunately for us,
there is no better tool for this task than Facebook.

What exactly the future holds is anyone’s guess, but what we do know is that, thanks to Facebook, your business will never again be the same—whatever your industry, wherever you work, and whether you are in marketing, IT, or another corporate function.