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.