How to reference C++ WRL Components from a .NET project

Whenever your Windows Runtime (WinRT) component has to implement COM interfaces as well as WinRT interfaces, Microsoft advises you to use the Windows Runtime Template Library (WRL), because the C++/CX – which otherwise is recommended to develop WinRT components – does not allow to implement COM interfaces.

However, if you are trying to use some of Microsoft’s publicly available samples from a .NET component, you might run into trouble. The problem is, that the winmd file that gets generated when you compile a WRL C++ Component – by default – does NOT reference the “Windows.winmd”-file, which provides the meta data for the WinRT API as a whole. Instead, it references only the particular winmd-files that describe partial areas of the WinRT API. These partial WinRT descriptions can all be found at a location similar to “C:\Windows\System32\WinMetadata”, whereas the complete WinRT API can be found at “C:\Program Files (x86)\Windows Kits\8.0\Windows Metadata\Windows.winmd”.

To demonstrate this problem I am referring to Microsoft’s “Real-time communication sample” that can be found at http://code.msdn.microsoft.com/windowsapps/Simple-Communication-Sample-eac73290. If you try to consume the “Microsoft.Samples.SimpleCommunication” component, which is part of the solution, from a Metro-style based C# application, you will have to add a reference to the components winmd-file (“Microsoft.Samples.SimpleCommunication.winmd”). Your C# application will still work fine. However, try to instantiate a class such as StspMediaSink next:

Microsoft.Samples.SimpleCommunication.StspMediaSink k = new Microsoft.Samples.SimpleCommunication.StspMediaSink();

This should produce the following error at compile time:
The type 'Windows.Media.IMediaExtension' is defined in an assembly that is not referenced. You must add a reference to assembly 'Windows.Media, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime'.

Metro-style based C# applications by default reference the WinRT API as a whole. This means that your project references the “Windows.winmd”-file. The problem now is, that the compiler is not smart enough to recognize, that the Windows.Media.IMediaExtension-interface, which is implemented by the StspMediaSink-class, is already defined in the referenced “Windows.winmd”-file. Instead it wants you to add a reference to the same “Assembly”.

You cannot simply go ahead and add a reference to the “Windows.Media.winmd”-file as requested. If you added a reference to Windows.Media.winmd the compiler would complain about ambiguous references to Windows.Media.IMediaExtension. Instead we have to modify the C++ Microsoft.Samples.SimpleCommunication-project in a way that it does not reference the “Windows.Media.winmd”-file anymore, but instead the “Windows.winmd”-file.

This can be achieved by adding the following custom build step to the C++ project:

Command Line: mdmerge -partial -i “$(OutDir).” -o “$(OutDir)Output” -metadata_dir “$(WindowsSDK_MetadataPath)” && copy /y $(OutDir)Output\* $(OutDir)
Outputs: $(OutDir)%(TargetName).winmd
Execute After: Midl

If you recompile the component now, you should be able to reference and consume it from your C# component. If you disassemble the component’s winmd-file, you will notice that it now references “Windows.winmd” and not the “Windows.Media.winmd”-file anymore.

In a future blog post I am going to describe how you can create your own WRL C++ project from scratch as Visual Studio 2011 currently does not ship a project template, unfortunately.

One thought on “How to reference C++ WRL Components from a .NET project

  1. I have tried the above procedure with the same sample simple communication, but the error is still persisting.This what I did

    1. Added the above commands as explained.
    2. Then rebuild Microsoft.Samples.SimpleCommunication.
    3. Rebuild the whole solution.

    But nothing happened the same error is still coming.

    Also by compiling the component you mean rebuilding “Microsoft.Samples.SimpleCommunication.”, right?
    Pls if I am doing something wrong pleas let me know.

Leave a Reply

Your email address will not be published. Required fields are marked *