Using the Windows Runtime from a Non-Metro Application

I know a lot of people believe that the new Windows Runtime APIs included in Windows 8 can only be accessed from Metro style applications. A big part of the reason why people believe this is because the version of Visual Studio that ships with the Windows 8 Developer Preview only supports creating Metro style applications. However, I set out this morning to use Windows Runtime APIs from a non-Metro application. Here’s what I did.

First, in Notepad, I created the following C# source code in EnumDevices.cs:

using System;
using System.Threading.Tasks;
using Windows.Devices.Enumeration;
using Windows.Foundation;

class App {
static void Main() {
EnumDevices().Wait();
}

private static async Task EnumDevices() {
// To call DeviceInformation.FindAllAsync:
// Reference Windows.Devices.Enumeration.winmd when building
// Add the “using Windows.Devices.Enumeration;” directive (as shown above)
foreach (DeviceInformation di in await DeviceInformation.FindAllAsync()) {
Console.WriteLine(di.Name);
}
}
}

Second, I created a Build.bat file which I run from the Developer Command Prompt to build this code (This should be 1 line but I wrap it here for read ability):

<

p style=”margin-left:36pt”>csc EnumDevices.cs
/r:c:WindowsSystem32WinMetadataWindows.Devices.Enumeration.winmd
/r:c:WindowsSystem32WinMetadataWindows.Foundation.winmd
/r:System.Runtime.WindowsRuntime.dll
/r:System.Threading.Tasks.dll

Then, at the command prompt, I just run the EnumDevices.exe to see the output.

Let me also explain how the async stuff works:

The XxxAsync methods (like DeviceInformation.FindAllAsync above) is a Windows Runtime method (defined in Windows.Devices.Enumeration.winmd) that returns a DeviceInformationFindAllAsyncOperation object which implements the Windows Runtime’s IAsyncOperation<TResult> interface where TResult is the Windows.Devices.Enumeration.DeviceInformationCollection type. This interface is defined in the Windows.Foundation.winmd file.

Using the await keyword causes the compiler to look for a GetAwaiter method on this interface. Since IAsyncOperation<TResult> does not define a GetAwaiter method, the compiler wants to look for an extension method. In the System.Runtime.WindowsRuntime.dll assembly is the static System.WindowsRuntimeSystemExtensions class. This class defines several GetAwaiter extensions methods and the compiler emits code that invokes the GetAwaiter extension method that takes an IAsyncOperation<TResult> and returns a System.Runtime.CompilerServices.TaskAwaiter<TResult> object (defined in the System.Threading.Tasks.dll which is why this assembly is referenced). Since TResult is the Windows.Devices.Enumeration.DeviceInformationCollection type, the await operator ultimately returns this type which is then used by the foreach loop. Inside the loop, I just display the Name property for each DeviceInformation object.

Because you cannot mark an entry point method (like Main) as being async, I moved the code that calls await into its own EnumDevices method, marked this method as async, and make it return a Task. Then Main invokes this method and calls Wait on the returned Task so that the application doesn’t terminate until EnumDevices has run all the way through to completion.

Jeffrey Richter

View Comments

  • Thanks for this blog post! I am hoping that WinRT will be usable from Desktop apps (officially); it would be nice to kiss p/Invoke goodbye.
    BTW, I have an AsyncContext class that is nice to use for async Console apps and unit testing (you can keep async void instead of changing to async Task). It's part of this library:
    http://nitoasyncex.codeplex.com/

  • Hi Jeffrey
    I know you always make things feel fundamental by bridging gap for old time programmers like me. Learnt VC++, and then .Net from your books. Now looking forward to learn this phenomenal new trend from Microsoft.

  • Thanks very much for this sample. I tried to build it on Consumer Preview 8250 x64 with the matching version of VS 11 Ultimate beta installed, and it would not compile. There appears to be some breaking change.
    First, a message said to add a reference to System.Runtime, so I added a ref to System.Runtime.dll to the command line.
    But then I got the following new error:
    enumdevices.cs(15,34): error CS4028: 'await' requires that the type
    'Windows.Foundation.IAsyncOperation Windows.Devices.Enumeration.DeviceIn
    formationCollection ' have a suitable GetAwaiter method. Are you missing
    a using directive for 'System'?
    The code already has "using System". I have tried many things, but cannot resolve this. For example, I searched and cannot find a version of System.Runtime.WindowsRuntime.dll on my system which lists GetAwaiter() in System.WindowsRuntimeSystemExtensions. (e.g. 4.0.30319)
    Any help in resolving this error will be appreciated! Thx.

  • I'm impressed, I must say. Really hardly ever do I encounter a blog that's each educative and entertaining, and let me tell you, you've hit the nail on the head. Your idea is outstanding; the issue is one thing that not sufficient individuals are speaking intelligently about. I am very joyful that I stumbled across this in my search for one thing relating to this.

Recent Posts

8-Step AWS to Microsoft Azure Migration Strategy

Microsoft Azure and Amazon Web Services (AWS) are two of the most popular cloud platforms.…

3 days ago

How to Navigate Azure Governance

 Cloud management is difficult to do manually, especially if you work with multiple cloud…

1 week ago

Why Azure’s Scalability is Your Key to Business Growth & Efficiency

Azure’s scalable infrastructure is often cited as one of the primary reasons why it's the…

3 weeks ago

Unlocking the Power of AI in your Software Development Life Cycle (SDLC)

https://www.youtube.com/watch?v=wDzCN0d8SeA Watch our "Unlocking the Power of AI in your Software Development Life Cycle (SDLC)"…

1 month ago

The Role of FinOps in Accelerating Business Innovation

FinOps is a strategic approach to managing cloud costs. It combines financial management best practices…

1 month ago

Azure Kubernetes Security Best Practices

Using Kubernetes with Azure combines the power of Kubernetes container orchestration and the cloud capabilities…

2 months ago