tags:

views:

61

answers:

1

If you want to use a COM type in your C# code, the process is straight forward, right? You just need to use the type library importer and that's fine, but what if you don't have one and you can't take a look at the IDL file? You just have the COM DLL server.

As an example, try using the IActiveDesktop interface.

What's the approch used to solve this kind of problem?

A: 

There are two kinds of COM interfaces. The one you are familiar with are the ones that restrict themselves to a subset of the COM spec known as "OLE Automation". Also known as ActiveX before that term became associated with security disasters.

Automation compatible interfaces are easy to use from just about any language. They typically inherit from IDispatch, allowing them to be used from scripting languages. And limit themselves to using only automation compatible types for their method arguments. The simple stuff, comparable to the .NET value types, BSTR for strings, SAFEARRAY for arrays, VARIANT for untyped arguments, quite similar to .NET's System.Object.

Another feature they support well is type libraries, the equivalent of .NET metadata. Used by a compiler to know how to call the interface methods. The IDE uses a type library to automatically generate the interop library so you can directly create the wrapper class and call the methods from .NET code.

Well, that's the good news. The bad news is that there are lots of COM interfaces around that do not use the Automation restrictions. They typically inherit from IUnknown and use function arguments that don't marshal well. Like structures. One very large and visible component in Windows that is like this is the shell. Windows Explorer.

That's where IActiveDesktop fits in as well, it is a shell interface and inherits from IUnknown. It is declared in the ShlObj.h SDK header file, there is not even a IDL file for it. And consequently no way to get a type library with its definition. It uses incompatible argument types, like LPCWSTR (a raw pointer to a string) instead of BSTR. And structure pointers like LPCCOMPONENT and LPWALLPAPEROPT. The CLR interop support is powerless to marshal that properly.

Using the interface in C# is technically not impossible, but you have to redeclare the interface. Very carefully, getting it wrong is very easy to do. The fact that source code that already does this is very hard to find is a hint how difficult it is. This squarely falls in the 'not impossible, but what sane programmer wants to maintain code like this' category. The shell is the domain of unmanaged C++ code. And a crew of hardy programmers, because debugging shell extensions is quite painful.

Hans Passant
that's one enlightening article, so if .NET interop requires that much hard work just to get basic interface stuff working, what's the alternative development route to take ?? MFC, VB or what ?? !
Ebraheem Najjar
It is not a .NET interop problem, you can actually use these interfaces. With an enormous amount of work. The *real* problem is that they were designed to be used from C++ code. Which, back 17 years ago, was expected. No way to fix that problem, they took the red pill back then. *Very* hard to make it blue.
Hans Passant
i dont have a problem with using C++ and the native api but they tend to be less productive when developing real apps, i thought of using C++/CLI to benefit from both native and managed code altogether and i was willing to sucrifice safe compilation but another problem rised, since C# supports WPF, WCF, .. and C++\CLI supports them through interop, so as a personal opinion what would u go for ??
Ebraheem Najjar
I'm not hardy enough to have ever wanted to pursue this. C++/CLI is the way to go, but they made it close to unusable in VS2010.
Hans Passant