Problem

I have recently migrated a C# 2.0 project registered for COM interop to .NET 4.5 and when I imported the type library in a C++ project with no_registry, suddenly I got some errors because the type library could not be imported. Here are the steps to reproduce:

  • create a .NET Class Library project and set platform target to .NET framework 4.5
  • check Register for COM interop
  • build the project
  • import the type library in a C++ project:

The result is the following error:

Solution

Searching for the solution I found that this was a known issue when you have both CLR 2.0 and 4.0 installed on the same machine. See this KB article: VC++ 2010 #import with no_registry fails with error C1083 or C3510. Unfortunately I was unable to fix the problem with the solution indicated there.

There are two tools that can generate a type library from an assembly:

  • tlbexp.exe: generates a type library from a specified .NET assembly
  • regasm.exe: registers metadata from an assembly to the Windows Registry, but in addition can create a type library from for the input assembly when /tlb switch is used.

When a project specifies to register for COM interop what Visual Studio does is similar to calling regasm.exe with /codebase switch specified. Since I had before problems with interop assemblies automatically generated by Visual Studio (with tlbimp.exe) I though it would be the same (only the other way around). Therefore I unchecked “register for COM interop” and added as a custom build step registration with regasm.exe, like this:

Not very surprisingly, the generated file was different and the #import command executed without problems.

Problem solved!

Cause

The question that arises is why are the two files, generated with Visual Studio and with regasm.exe, different? You can see they are different if you open them in an hex editor. But if you just use oleview.exe, the disassembled type library looks identical.

The obvious answer that occurred to me, but eventually proved wrong, was that Visual Studio is not actually using regasm.exe to register the assembly and generate the type library. It actually uses a MSBuild task for that.

When the RegisterForComInterop property is set in a .csproj an MSBuild task is executed.

The task can be found in Microsoft.Common.targets (in c:\Windows\Microsoft.NET\Framework\v4.0.30319\)

To check if I can reproduce, I have created MSBuild file (explicitreg.xml) with some hard-coded values that only runs that registration task.

But surprise: this produced the exact same output as the regasm.exe command. Comparing the diagnose logs from MSBuild (for the build of the .csproj and my custom file) I couldn’t spot any difference in the execution of the task. Also using the Process Monitor (procmon.exe from Sysinternals) to check access to the TLB file, I could clearly see the difference for the file writing, because different lengths were produced from Visual Studio build and explicit MSBuild run, though again I could not see any difference in the call stacks.

So, the actual cause for this behavior is still unknown to me and I would appreciate if anyone that knows the answer clarifies it.

, , , , , , , Hits for this post: 48738 .

Not long ago I ran into a COM interop problem that was a bit tricky to fix. So I’m sharing the problem and the solution here in case others encounter the same problem.

I had this native in-proc COM server that initially was built only for x86. It was used in a native MFC application as well as a C# Windows Forms application, where it was added as a COM reference. Both worked nicely. But then I needed to port the MFC app to the x64 platform, so I had to do the same with the in-proc COM server. They both worked correctly, but the managed app, which had to be available also both as 64-bit and 32-bit (even on 64-bit machines), was broken. Eventually I traced the problem to some COM method calls which were a bit atypical, because the arguments to the methods were not COM “native” types, but custom structures.

These structures looked like this:

and the COM method signature:

When you add a COM reference to a .NET assembly, Visual Studio runs tlbimp.exe to generate a .NET assembly with equivalent definitions to the type definitions found in the COM type library. This interop assembly is used to access the COM server. It contains Runtime Callable Wrappers that bridge the two worlds together. By default, the interop assembly, generated in the project’s output folder, is called Interop.<comname>Lib.dll. For instance if the COM server is called NativeCOMServer, the interop assembly is called Interop.NativeCOMServerLib.dll.

The wrapper that was generated in the interop assembly had the following signature for the aforementioned method:

and therefore used like this:

The call was performed correctly, the native code was executing, but as soon as it was returning an access violation exception was occurring. Thanks to Hans Passant I figured the problem was rooted in the way Visual Studio generates the interop assembly. The generated RCW didn’t know how to handle the custom structure correctly. Probably different padding on the two sides generated the access violation.

The trick was to generate the interop assembly directly, as a custom build step in the COM server project, and include it as an assembly reference in the managed project. Here are the commands for the custom build (must to make sure you have the correct path to the 32-bit and the 64-bit version of tlbimp.exe):

The result was a wrapper with methods like this:

which of course had to be called like this:

To include either one or the other in the C# project I had to manually change the project file, since Visual Studio does not know conditional references, a feature available in MSBuild. I didn’t build the managed app for Any CPU because it had to be able to run as 32-bit on 64-bit machines, so I had two configurations, one for x86 and one fore x64.

But this time the wrappers were able to bridge the call and everything worked smoothly.

The lesson learned is that when you have COM custom structures you should not rely on the way Visual Studio generates the interop assembly. You should build the interop explicitly (maybe as a custom build step, like I did) and include it as an assembly reference to your managed project.

, , , , , , Hits for this post: 47801 .

Windows Runtime, or shortly WinRT, is a new runtime (siting on top of the Windows kernel) that allows developers to write Metro style applications for Windows 8, using a variety of languages including C/C++, C#, VB.NET or JavaScript/HTML5. Microsoft has started rolling out information about Windows 8 and the new runtime at BUILD.

(source www.zdnet.com)

WinRT is a native layer (written in C++ and being COM-based) that is intended as a replacement, or alternative, to Win32, and enables development of “immersive” applications, using the Metro style. Its API is object oriented and can be consumed both from native or managed languages, as well as JavaScript. At the same time the old Win32 applications will continue to run just as before and you can still (and most certainly will) develop Win32 applications.

Microsoft has created a new language called C++ Component Extension, or simply C++/CX. While the syntax is very similar to C++/CLI, the language is not managed, it’s still native. WinRT components built in C++/CX do not compile to managed code, but to 100% native code. A good news for C++ developers is that they can use XAML now to build the UI for immersive applications. However, this is not available for classical, Win32 applications.

You can get a glimpse of the new system and the tools by downloading and installing the Windows Developer Preview with tools, that includes the following:

  • 64-bit Windows Developer Preview
  • Windows SDK for Metro style apps
  • Microsoft Visual Studio 11 Express for Windows Developer Preview
  • Microsoft Expression Blend 5 Developer Preview
  • 28 Metro style apps including the BUILD Conference app

Notice this is a pre-beta release and you might encounter various problems.

Before you start here are several additional articles that you might want to read:

There are also several new forums available on MSDN forums for developing Metro style applications, which you can use for addressing technical questions. Hopefully thee will be answers from Microsoft people working in this area.

, , , , , , , , , Hits for this post: 69592 .

I’ve ran recently across this question: how to find (using C++) if a computer is a laptop? That is possible with WMI and many answers (such as this) point to the Win32_SystemEnclosure class. This class has a member called ChassisTypes, which is an array of integers indicating possible chassis types. At least one of them should indicate a laptop. However, there might be several problems with this solution. First, there are several values for “laptops”:

  • 8 – Portable
  • 9 – Laptop
  • 10 – Notebook

Different machines might return different values. And more important, this property might not be defined on all computers. A more reliable solution is explained in this TechNet article Finding Computers That Are Laptops. The solution described there suggests checking for several properties:

  • Win32_SystemEnclosure, ChassisTypes(1)=10.
  • Win32_Battery or Win32_PortableBattery.
  • Win32_PCMCIAController
  • Win32_DriverVXD.Name = “pccard”
  • Win32_ComputerSystem.Manufacturer
  • Win32_ComputerSystem.Model

The following code shows how one can query for the chassis types using C++. Run queries for the other properties to make sure you are running on a laptop.

On my laptop, the program output was:

Name: System Enclosure
Chassis: Notebook

, , , Hits for this post: 38699 .

It is possible to register both 32-bit and 64-bit versions of the same COM server on 64-bit machine. This leads to several questions such as how are they registered and which one of the two is used. I will try to answer them below. But first, let’s start with an example.

Example
Let’s say we have the a simple COM local server called COM3264Server.exe. There is just one interface called ICoCOM3264Server. Here is the IDL file:

The implementation of the method SayHello() is straight forward; it just displays a message box with a text that varies between the two architectures, x64 and x86.

Registry
When you register the COM server, the 32-bit and 64-bit versions are registered in different parts of the registry. On 64-bit machine, the registry has two views (or modes):

  • a native view, for 64-bit application; (e.g. registry path for CLSIDs is HKEY_CLASSES_ROOT\CLSID\)
  • a WOW64 view, which enables redirections for 32-bit applications, a process transparent to the user (e.g. registry path for CLSIDs is HKEY_CLASSES_ROOT\Wow6432Node\CLSID\)

Here is the Registry registration of the (native) 64-bit COM server (notice the registry key in the status bar of the editor, and the path to the server executable).

On, the other hand, the 32-bit COM server is registered under the Wow6432 node.

So if both versions are registered in Windows Registry, which one is picked? Well, both the server and the client can specify which architecture to use:

  • the COM server can do this via the PreferredServerBitness Registry value
  • the client can do this using one of the flags CLSCTX_ACTIVATE_32_BIT_SERVER and CLSCTX_ACTIVATE_64_BIT_SERVER, which overrides the server preference

If neither the client nor the server specifies a preference, then:

  • If the computer that hosts the server is running Windows Server 2003 with Service Pack 1 (SP1) or a later system, then COM will try to match the server architecture to the client architecture. In other words, for a 32-bit client, COM will activate a 32-bit server if available; otherwise it will activate a 64-bit version of the server. For a 64-bit client, COM will activate a 64-bit server if available; otherwise it will activate a 32-bit server.
  • If the computer that hosts the server is running Windows XP or Windows Server 2003 without SP1 or later installed, then COM will prefer a 64-bit version of the server if available; otherwise it will activate a 32-bit version of the server.

Server Preference
The server can specify its preferred architecture in the PreferredServerBitness value under AppId (available only on 64-bit Windows). This integer value can be:

  • 1: Match the server architecture to the client architecture. For example, if the client is 32-bit, use a 32-bit version of the server, if it is available. If not, the client’s activation request will fail.
  • 2: Use a 32-bit version of the server. If one does not exist, the client’s activation request will fail.
  • 3: Use a 64-bit version of the server. If one does not exist, the client’s activation request will fail.

Here is the value set in Registry to specify the 64-bit architecture.

When you run the client, it launches the 64-bit version and in my example the following window pops-up:

If I change the value to indicate the 32-bit architecture, the other COM server is launched and the displayed message is:

Client Preference
The client code I used so far looked like this:

However, the 64-bit version of Windows added new flags to the CLSCTX enumeration.

  • CLSCTX_ACTIVATE_32_BIT_SERVER: used to activate or connect to a 32-bit version of the server; fail if one is not registered.
  • CLSCTX_ACTIVATE_64_BIT_SERVER: used to activate or connect to a 64 bit version of the server; fail if one is not registered.

As I mentioned earlier, if the client uses one of these flags, it overrides the server preference (specified via the PreferredServerBitness Registry value).

In the following example, the client requests the 64-bit COM server:

And if you run it, no matter what the server specified, the 64-bit COM server is launched.

To read more about the subject see the MSDN links above.

, , , Hits for this post: 58978 .

COM Apartments

If you work with COM, apartments is one of the concepts you must comprehend, because it’s an important topic. Before explaining what apartments are let’s think about classes and objects regardless of COM. When you build a class, you know (or you should) whether objects of that class will be used from a single thread, or from multiple threads. In the later case, if those threads might access shared data at the same time, you must synchronize the access to that data (using critical sections, mutexes, or others). So when you create your class you either make it thread-safe or not. If it’s not thread safe, objects of that class can only be accessed from one thread at a time, if it’s thread-safe, then objects of that class can be accessed from different threads at the same time.

Now, the same rule applies in the COM world. Your coclasses can either be thread-safe or not. If the are thread-safe, you can access one object from different threads at a time, otherwise not. Here enter the apartments. So what is an apartment? An apartment is an environment in which COM objects can live. It’s not a thread, nor a process, but it handles access from COM clients to COM objects. There are several types of apartments: single-threaded apartments (STA), multi-threaded apartments (MTA) and neutral-threaded apartments (NTA).

Single-Threaded Apartments
An STA allows only one thread at a time to access a COM object. This is achieved using a hidden window with a message pump. Calls from clients living in different threads are queued with the message pump. Only when the current call from a thread ends, the next call can proceed.

Assume you had a COM object called CoUserGroups that implements an interface IUserGroups that provides two methods: one called Add that adds a new user group, and one called Delete that deletes a user group. Since both methods work on the same list of user groups, adding and deleting is not possible at the same time without synchronizing access. But since such synchronization was not implemented, the COM object specifies that it can leave only in an STA, and let the apartment do the synchronization of calls from clients living in different threads.

Multi-Threaded Apartments
An MTA allows any number of threads to access a COM objects. However, the COM objects must be thread-safe, otherwise your application will behave unexpectedly and even crash.

Going back to the previous example, if CoUserGroups was implemented in a thread-safe manner, then it would be possible for clients living in different threads to access it. In this case there would be no need for an apartment level synchronization. The COM coclass specifies that it can live in an MTA and when simultaneous calls from different threads are received they are directed immediately to the COM object. This situation is shown in the next image.

Neutral-Threaded Apartments
NTAs, like MTAs, allow multiple threads to enter one apartment, but once a thread entered the apartment it acquires an apartment wide lock that will block the other threads, until the current thread exists the apartment. Calls into NTA (from STA or MTA in the same process) do not generate context switches; the thread leaves the apartment in which it executes and enters the NTA without any context switch, which increases performance. This model was introduced with COM+ (in Windows 2000) and is meant for components with no user interface.

A process can contain several apartments:

  • zero or one MTA
  • zero or one NTA
  • zero, one or several STAs; the first STA created for a process is called the main STA

As a COM client, you specify the apartment you want to join with a call to CoInitializeEx(). This methods must be called from each thread.

The second parameters is a set of flags specifying the initialization options for the thread. To join the unique MTA, use COINIT_MULTITHREADED. To join a new or existing STA, use COINIT_APARTMENTTHREADED. Function CoInitialize() calls CoInitializeEx() specifying COINIT_APARTMENTTHREADED for the flags.

How to specify the threading model allowed for a coclass?
A coclass can specify the type of apartment it can join. If you’re using ATL you can specify that when you create the coclass. The next image shows the available options:


What they mean:

  • Single: object wants to join the main STA (the first STA created into the process)
  • Apartment: object wants to join one of the STAs in the process
  • Both: object wants to join either an STA or the MTA
  • Free: object wants to join the MTA
  • Neutral: object wants to join the NTA

ATL adds the appropriate value to the registry script it creates for your coclass. COM depends entirely on the registry, and the threading model is also specified in the registry. Here is an example:

When that is merged into the Windows Registry, it looks like this:

The possible values in registry are:

  • no value specified: equivalent of ATL ‘Single’
  • Apartment: equivalent of ATL ‘Apartment’
  • Free: equivalent of ATL ‘Free’
  • Both: equivalent of ATL ‘Both’
  • Neutral: equivalent of ATL ‘Neutral’

If you want to read more about COM apartments I suggests articles like this one.

, , , , , , Hits for this post: 46506 .

COM and Registry

If you are working with COM there are several registry entries that are important and that you need to understand. I will try in this post to clarify them. But before that, let’s enumerate the three possible COM server scenarios. (As a side note, a COM server is a DLL or EXE can contains one or more COM objects; a client is an entity that uses a COM object, which means a COM server can also be the client of another COM server.)

  • inproc: the COM server is loaded into the client process; in this case accessing the COM methods is as simple as using an interface pointer when the client and the in-proc server are in the same thread
  • local: the COM server and the client are loaded in different processes on the same machine; communication is achieved with the use of proxies and stubs via Lightweight RPC
  • remote: the COM server and the client are loaded in different processes on different machines; communication is achieved with the use of proxies and stubs via RPC

In order for the COM Library to be able to locate and instantiate the COM objects correctly, different information is stored in the Windows Registry. The most important information is located under the keys CLSID, TypeLib, Interface and AppID from HKEY_CLASSES_ROOT. The images below show examples for IIS.

HKEY_CLASSES_ROOT\CLSID
Every coclass from the COM server has at least an entry under this key, specifying the CLSID and the ProgID. The CLSID is a GUID that uniquely identifies the class, and the ProgID (programmatic identifier) is a string that identifies the class in a more human readable form. Each ProgID is mapped to a CLSID. The following image shows the mapping for the IIS ProgID.

For each COM class, there must be a key under HKEY_CLASSES_ROOT\CLSID, with the CLSID as the name. The most important sub-keys here are:

  • ProgID: the programmatic identifier, mapped on the CLSID; cam contain a version number (as a suffix)
  • VersionIndependentProgID: a programmatic identifier without the version information
  • InprocServer32: specifies the path of the DLL for the inproc servers
  • LocalServer32: specifies the path of the COM executable for the local (out-of-process) servers
  • TypeLib: indicates the LIBID of the type library that contains the coclass

Here are several screenshots from registry for IIS CLSID.


HKEY_CLASSES_ROOT\TypeLib
Each type library has a key under HKEY_CLASSES_ROOT\TypeLib, with the name of the LIBID. The sub-keys provide information about the physical location of the type library file (.tlb file) and others, such as flags (FLAGS key) the directory that contains the help file for the type library (HELPDIR key). A LIBID is a GUID that uniquely identifies a type library. A *.TLB file is a binary version of an IDL file. This is used by languages such as VB, Java, Javascript and many others in order to be able to use the COM objects.

The following image shows the type lib information for IIS.

HKEY_CLASSES_ROOT\Interface
Information for all interfaces defined in an IDL file (type library) must be added to the registry. Under HKEY_CLASSES_ROOT\Interface must be a key with the IID of the interface. The IID (interface identifier) is a GUID that uniquely identifies an interface. The most important sub-keys are:

  • TypeLib: the LIBID of the type library containing the interface
  • ProxyStubClsid32: the CLSID of the marshaller used to marshal the interface; value {00020424-0000-0000-C000-000000000046} identifies oleaut32.dll, which is the universal marshaler.

The following images show the registry entry for the interface IISBaseObject.

HKEY_CLASSES_ROOT\AppID
An AppID (application identifier) is a GUID that uniquely identifies a COM server and is used to describe security and activation settings; it is used for out-of-proc (local or remote) scenarios. Usually the AppID is the same with a CLSID of a coclass from the COM server (without the risk of collision, because the CLSID and the AppID server different purposes). The most important settings are:

  • AccessPermission: defines the ACL of users that can access the server
  • AuthenticationLevel: defines the authentication level
  • DllSurrogate: identifies the surrogate that can host the DLL; if no value is specified, the default dllhost.exe surrogate is used
  • LaunchPermissions: defines the ACL of users that can launch the application
  • RemoteServerName: identifies the remove server machine

The following images shows the values for an AppID key.

, Hits for this post: 43445 .

.NET allows you to expose components as COM and consume them from unmanaged code. There are many references on how to this (and you can only start with MSDN), and I will not talk about that part. What I want to explain here is something different. Suppose you have this interface:

Method GetUsers() returns an array on string representing the user names. But what if you also wanted the user passwords or addresses? Since this is exposed as COM, you cannot return an array of User. But you can return multiple arrays of string. So, how would you deal with out string[]? This is what I want to show you in this tutorial.

This is a .NET interface exposed to COM. It has two methods, GetUsers() that returns an array of string representing user names, and GetUsers2() that returns an array of strings as an output parameters and a bool as return type, indicating whether any user was found.

And this is the implementation:

Note: If you are trying this example make sure you set the ComVisible attribute to true, either for each type or per assembly (in AssemblyInfo.cs)

Second, you have to check the “Register for COM interop” setting in the Build page of the project properties.

The first thing to do in C++ is importing the .TLB file that was generated by regasm.exe.

If we look in the .TLB file, we can see how the IAccounts interface looks like:

The following C++ functions, GetUsers1() retrieves the users users list using method GetUsers() from IAccounts. It puts the users in a CStringArray (notice that this container does not have an assignment operator, so the only way to return such an array is with a reference in the parameters list).

UnpackBstrArray() is a function (see below) that extracts the elements of a SAFEARRAY and adds them to a CStringArray.

Function GetUsers2() uses the second method, GetUsers2() from IAccounts. This needs the address of a pointer to a SAFEARRAY (i.e. SAFEARRAY**) that will hold the values returned by the COM method. This time we have to create an empty SAFEARRAY and then pass its address to the COM method. The rest is similar to the previous case.

The helper method UnpackBstrArray() used previous looks like this:

Attached you can find a demo project (C# and C++) with the complete example show in this tutorial.

output SAFEARRAY** example (1278)

, , , , , Hits for this post: 58701 .