Creating managed wrappers for COM interfaces

COM interop can be a very useful tool, but it requires the definitions of the unmanaged interfaces one wants to use. This may be a little tricky, so here’s a small guide to help you out. Note that much of the advice below is applicable to P/Invoke as well.

Make sure it’s necessary

Many COM APIs have managed counterparts, so make sure you don’t waste your time doing what the BCL team already did for you. A quick search would usually lead you to the right StackOverflow / MSDN page. Make sure you check the Windows API Code Pack too.

See if it’s been done

Many times, the interface you want to use has already been written in managed form. For example, IPersistFile is already defined in mscorlib.dll (hint: you already have this referenced in your project by default) under the System.Runtime.InteropServices.ComTypes namespace.

A quick MSDN search should start you off in the right direction – you’d be surprised where you find some of them… For example, Microsoft.VisualStudio.TestTools.UITest.Extension contains IUniformResourceLocator, and Microsoft.VisualStudio.OLE.Interop contains IPropertyStorage. Searches beyond MSDN could be worthwhile as well, especially note PInvoke.net. Another useful source is Ohloh code search (note that you can filter by language, e.g. C#).

If you don’t want to take a dependency on the assembly that has the definition you want, you can always copy the definitions you need to your source (e.g. from Reflector).

Another repository of managed code definitions is embedded in the P/Invoke Interop Assistant (more on this tool later).

Use TlbImp

Sometimes you won’t find the interface you want defined anywhere. Fortunately, TlbImp can automatically create the needed managed COM definitions for you, provided that you can feed it with the appropriate type library (.tlb) files (note that these could be embedded in EXE and DLL files as resource) .

That would have been straightforward had the OS / SDK actually come with tlb files for the entire Win32 COM API, but that is not always the case. Instead, you can usually find an interface definition (.idl) file containing the interface you desire (use findstr or something like find in files in Notepad++).

Once you find the relevant IDL file, you will need to compile it into a TLB file, which in turn could be fed to TlbImp. The midl compiler does just that, but it will only produce tlb files for Library definitions, which may not be present. Fortunately, we can simply inject some Library definition with the interfaces we want into the IDL file and thus “trick” midl into producing the tlb.

For example, suppose you want to get the managed definition of the IPropertySetStorage interace, which resides in [SDKFolder]IncludeumPropIdl.Idl. 

  1. Open PropIdl.Idl in your favorite text editor
  2. Add the following after the definition of IPropertySetStorage:
    [ uuid( 03383777-9430-4A45-9417-38B4B5CB4143 )] // (use guidgen.exe to generate this guid)
    library TempLib {
    interface IPropertySetStorage;
    }
  3. Run midl PropIdl.Idl
  4. Run tlbimp PropIdl.tlb
  5. Don’t forget to undo your changes to PropIdl.Idl !

You will now have TempLib.dll containing all the required definitions for the interface.

Use the P/Invoke Interop Assistant

Sometimes you can’t even find IDL definitions for the interfaces you want, and in those cases you have to go hardcore and define them yourself. Note that you should look at the unmanaged definitions in the header (.h) file itself (again find it in the SDK folder with findstr or a similar tool) rather than the MSDN documentation, as definition order is very important and the docs don’t preserve it. MSDN may also present the signatures of the ANSI interface, whereas you’d likely want the Unicode variety (in the header file, they will be defined as InterfaceA for ANSI and InterfaceW for Unicode).

As for the signature conversion itself, the CLR Interop team has released the P/Invoke Interop Assistant to, well, assist you with that. Basically, you paste in the unmanaged signature of the interface / struct you want to use (grab them from MSDN), and it generates the managed definitions for you. Note that it may need your help sometimes for typedefs it doesn’t know (in these cases you need to “unwrap” the typedefs until you reach something it knows,  usually a basic type) so browsing the actual header files in Visual Studio may be more convenient (simply start a new Win32 project and include the desired header).

For more information on marshaling data between managed and unmanaged code see Marshaling Data with Platform Invoke. The P/Invoke Data Types table and the COM Data Types table are great cheat-sheets to have handy, too.

Don’t let Work Guy screw Home Guy over

A great man once said:

I never get enough sleep. I stay up late at night, cause I’m Night Guy. Night Guy wants to stay up late. ‘What about getting up after five hours sleep?’, oh that’s Morning Guy’s problem… That’s not my problem, I’m Night Guy – I stay up as late as I want! So you get up in the morning, you’re exhausted, groggy… oooh I hate that Night Guy!

See, Night Guy always screws Morning Guy. There’s nothing Morning Guy can do. The only Morning Guy can do is try and oversleep often enough so that Day Guy looses his job and Night Guy has no money to go out anymore.

Today, after tackling some annoying WCF issues at a late hour, I realized Work Guy and Home Guy have a very similar relationship.

When I’m at work , I stay to work late cause I’m Work Guy. I  want to track down that bug, I want to finish that piece of code, I want to get that test to pass, I want to study that interesting .NET topic a little further.

“What about getting home at 10:00 PM, missing the gym session you wanted to have, skipping that UFC title fight event you wanted to watch, and delaying that level you wanted to complete in your latest video game?”, oh that’s Home Guy’s problem – I’m Work Guy, I stay at work as late as I want!

So you get home late, and by the time you eat, shower, and write a small blog post you have to go to bed… ooh I hate that Work Guy ! It’s a good thing that by that time you’re already Night Guy, so you can stay up late 🙂