Managed desktop apps and Windows Runtime
[ This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation ]
Visual Studio has made it extremely easy to write managed Windows Store apps that consume Windows Runtime APIs. However, if you’re writing a managed desktop app, there are a few things you’ll need to do manually in order to consume the Windows Runtime APIs. This paper provides information about what you need to do so that your desktop app can consume the Windows Runtime APIs. It assumes that the reader is familiar with writing managed desktop apps. This information applies to Windows 8.
Visual Studio has been enhanced to make Windows Store app development incredibly simple, including the ability to easily consume new Windows Runtime APIs. This extra simplicity gets activated when you choose to create one of the new “Windows Store” project types.
However, if you create a new managed desktop app that consumes the new Windows Runtime APIs, there are some things you need to do manually. In this paper, I’ll list out some tips to help you do this.
Targeting Windows 8
After you’ve created your new managed desktop app, you need to make one manual tweak in the project file to tell Visual Studio that you want to target Windows 8:
<PropertyGroup> <TargetPlatformVersion>8.0</TargetPlatformVersion> </PropertyGroup>
This is required in order to add references to Windows Metadata files.
For step-by-step directions, take a look at How to: Add or Remove References By Using the Reference Manager, and scroll down to Windows Tab -> Core Subgroup.
Consuming standard Windows Runtime types
As a reminder, the MSDN library documentation identifies each Windows API as being applicable to desktop apps, Windows Store apps, or both. Therefore, from your desktop apps, make sure that you only use APIs documented with this:
- Applies to: desktop apps only
- Applies to: desktop apps | Windows Store apps
Furthermore, each API might have its own set of documented caveats or dependencies (for example, some APIs only work when there is a UI framework created). So be sure to read through the documentation for each Windows Runtime class you intend to use, to make sure it will work with your desktop app.
That said, your desktop app can’t consume much of anything from the Windows Runtime until you prepare your project with one essential reference. The Windows Runtime defines some standard classes and interfaces in System.Runtime, such as IEnumerable, that are used throughout the Windows Runtime libraries. By default, your managed desktop app won’t be able to find these types, and so you must manually reference System.Runtime before you can do anything meaningful with Windows Runtime classes. To create this manual reference:
1. Navigate to your managed desktop app project in the Solution Explorer.
2. Right-click the References node and click Add Reference.
3. Click the Browse tab.
4. Click Browse….
5. Navigate to the System.Runtime.dll façade. You can generally find this in a path similar to: %ProgramFiles(x86)%\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\Facades\System.Runtime.dll
Now you can add references to other Windows metadata files and use the applicable Windows Runtime APIs for your desktop app.
Consuming Windows COM APIs
Windows 8 contains some useful new APIs available via COM. This might seem out of scope here, but these new COM APIs are often used in conjunction with the Windows Runtime to work with some of the new Windows features around the Windows Store app model. For example, if you’re writing a managed desktop app that enumerates over installed Windows Store app packages, you might use the Windows Runtime PackageManager class to discover those installed Windows Store apps, in conjunction with the COM interface IAppxManifestReader to retrieve information about those Windows Store apps from their manifest.
To consume these COM interfaces, you’ll need to generate a type library and then a managed assembly containing the definitions of those COM interfaces:
1. Open a Developer Command Prompt for Visual Studio.
2. Run a command similar to this to generate the type library: midl %ProgramFiles(x86)%\Windows Kits\8.0\Include\winrt\<IDL Filename> /out <path>\<TLB Filename>
3. Run a command similar to this to convert the type library you just generated into a .NET assembly: tlbimp <path>\<TLB Filename> /namespace:<Namespace> /out:<path>\<Assembly filename>
4. Now, inside Visual Studio, add a reference to the assembly you just created:
a. Navigate to your managed desktop app project in the Solution Explorer.
b. Right-click the References node and click Add Reference.
c. Click the Browse tab.
d. Click Browse….
A couple of troubleshooting steps to be aware of.
In some cases you might be able to skip generating the .NET Assembly in step 3, and just directly add a reference to the type library you created in step 2 in Visual Studio’s Add Reference dialog box. However, this doesn’t always work, and Visual Studio might fail when you try to reference some type libraries you create this way. In such cases, you can usually get things working by generating and referencing a .NET assembly as in steps 3 and 4.
When you add the reference to the .NET assembly in step 4, by default Visual Studio sets Embed Interop Types to True. You can view this by right-clicking the newly-referenced assembly under the References folder in the Solution Explorer. This setting may cause errors later when you compile your project, such as error CS1752: Interop type '<type name>' cannot be embedded. Use the applicable interface instead.
This is a pretty common problem, often with an easy solution. See Interop Type Cannot Be Embedded for more information.