Windows 8: Using WinRT APIs in Desktop Apps
Published on Monday, October 1, 2012 4:12:05 PM UTC in Programming & Tools
It's not a secret that desktop applications are able to use certain WinRT APIs too. In some of the documentation, for example that of the Accelerometer class, you can read:
**Applies to: **Windows Store apps | desktop apps
There's even an overview list of all the WinRT classes that can be used from the desktop, conveniently compiled and linked to on a single page. So clearly there must be a way to include them in your normal, non-Windows Store applications. But when I tried to actually do that, I found little to no documentation on it and was struggling to set up everything.
TL;DR: to use WinRT in desktop applications, you need to manually edit your project file. Methods that worked in the preview versions do not succeed anymore.
When you create a new desktop application, let's say using the WPF template, there is no Windows.* namespace available. My first attempt therefore was to add a reference to the required assemblies. But what are the required assemblies? When you use the the Reference Manager dialog in Visual Studio 2012, there's no assembly starting with that name listed in the GAC, and also no assembly on the COM tab that would look like the WinRT things. After poking around on my hard disk for some time without reasonable results I remembered that I had played with the meta data format a bit some months ago, and also concluded that the WinRT APIs would be part of the Windows SDK, or at least not located closely to the .NET bits. So finally I found the "Windows.winmd" meta data file in a program files folder:
A quick search on the web revealed that apparently in the preview versions this indeed was the way to get access to those APIs: simply add a reference to that meta data file to your normal desktop applications. That procedure is described here, for example. However, in the final version of Visual Studio 2012, this results in a reather chatty error message:
At first, the message lost me somewhere after "Core subgroup section", but reading it more carefully I realized that I should probably simply take a look at the referenced help page to see what's described there:
The Core tab lists all of the WinMDs in the SDK for the targeted version of Windows.
In the desktop projects, the Core tab doesn’t appear by default. The user can choose to code against the Windows Runtime by opening the shortcut menu for the project node, choosing Unload Project, adding the following snippet, opening the shortcut menu for the project node again, and then choosing Reload Project. Now, when the user invokes the Reference Manager dialog box from the project, the Core tab will appear.
In plain English: you have to edit the project file manually for your current project to add some hint to it that you want to target Windows 8. Only by doing that will a separate tab in the Reference Manager appear that lets you select the WinRT APIs as reference.
Insert the following snippet as new property group anywhere into the project file:
<PropertyGroup> <TargetPlatformVersion>8.0</TargetPlatformVersion> </PropertyGroup>
Save, close the project file, and select "Reload project" in the popup menu of the project node in solution explorer (shown above) which will open the project normally again. Now when you open the Reference Manager, you will see a new tab available, the same that we have in Windows Store Apps:
When you look at the tooltip, you can see that it indeed points to the same winmd file that we tried to manually add before:
As you can see the version number reads 255.255.255.255. That is because despite sharing the same meta data format (that requires a version number in its assemblies), WinRT doesn't use version numbers for e.g. type resolution. At some point, the decision has been made to use that arbitrary version to at least work around some potential problems with .NET type resolution.
Anyway, by adding that reference you have now access to the WinRT classes and can start experimenting with them:
I think it's a bit unfortunate that you have to go through the process of manually editing your project file to get access to the WinRT APIs in desktop applications. It once again feels a bit like not being treated as first class citizen anymore when you want to create desktop apps. At least I would've expected more guidance for example conveniently put next to the list of supported APIs, because at the moment that information is nothing you easily bump into when you fire up your search engine. If you have no idea of winmd files and the background story, my guess is that you'll really have a hard time finding out what to do. And even if you do, you probably muddle through the same error messages and Visual Studio documentation I went through to find the correct snippet that'll help you achieve what you want. That's not exactly the developer experience I want, and I hope sharing this will spare some of you the same.