2012

Volume 27

Windows Runtime Components - Windows Runtime Components in a .NET World

By Jeremy Likness | 2012

The new type of program known as a Windows Store app—optimized to run on Windows 8 devices—has a default view with a full-screen window and no distracting chrome, so the content is the focal point. Windows Store apps support fluid layouts that adapt and scale to a variety of screen sizes and resolutions. They provide a touch-first experience while providing full support for the traditional keyboard and mouse.

Windows Store apps run on a new set of APIs called the Windows Runtime (WinRT). The Windows Runtime exposes components that are built as part of the Windows 8 OS along with third-party components you can develop yourself. Although some core Windows Runtime Components are accessible from desktop apps, third-party Windows Runtime Components are only available from within the Windows 8 environment. WinRT types are described using WinRT metadata files that have the .winmd extension. These files are encoded using the same standard the Microsoft .NET Framework uses for providing metadata definitions and semantics for classes, ECMA-335 (see bit.ly/sLILI).

You can quickly navigate to the type definitions on a Windows 8 machine by changing to the directory that contains system files for Windows (usually c:\windows\system32). A folder within that direc­tory called WinMetadata contains all of the type definitions. You can use the ILDasm.exe utility to explore the types. Open a Visual Studio 2012 command prompt, navigate to the c:\windows\system32\WinMetadata folder and type the following in the command line:

Ildasm.exe windows.web.winmd

You should see a result similar to Figure 1. You can use the ILDasm.exe utility to inspect all of the namespaces and types defined for that particular Windows Runtime Component.

Inspecting WinRT Types
Figure 1

What’s interesting to note is that there’s no code contained within the file; only metadata information is available. The component is part of the underlying OS. It’s most likely written using native code. A unique feature called language projection allows Windows Runtime Components (both native and managed) to be accessed from any language that supports Windows Store app development.

Projection and Mapping

Many languages, including C#, Visual Basic, C++ and JavaScript, have been updated with Windows 8 to support language projection. This allows Windows Runtime Components to be accessed in a natural way using multiple languages. Projection handles exposing a WinRT type as an object or class that’s native to the language being used to develop the Windows Store app. The following code accesses a native Windows Runtime Component directly from a Windows Store app built using C#:

var ui = new CameraCaptureUI();

The CameraCaptureUI is a Windows Runtime Component. The component isn’t a managed C# type, but it can be easily accessed and referenced from within C# code as if it were. This is because the CLR automatically generates a Runtime Callable Wrapper (RCW) for the Windows Runtime Component using its metadata and causes it to appear as a native CLR type to managed code. For more on this, see the MSDN Library article, “Runtime Callable Wrapper,” at bit.ly/PTiAly. The RCW makes it easy and straightforward to interact with these components. The reverse is also true. Projection enables a Windows Runtime Component created with managed code to be referenced like a C++ type from native code and as a JavaScript object from within HTML/JavaScript projects.

Fundamental types appear automatically as C# types. The Windows Runtime has an ELEMENT_TYPE_STRING type that appears in .NET code as a String object. The ELEMENT_TYPE_I4 scalar appears as an Int32. The CLR will also take certain WinRT types and map them to appear in code as their .NET equivalents. For example, the WinRT type for a fixed-sized collection is IVector<T>, but this type will automatically appear as an IList<T> in .NET code. A WinRT HRESULT appears in the .NET Framework as an Exception type. The CLR will automatically marshal these types between the managed and native representations. Some types, such as streams, can be converted explicitly using a set of extension methods provided by the CLR. For a full list of types that are mapped in this fashion, refer to the MSDN Dev Center topic, “.NET Framework Mappings of WinRT Types,” at bit.ly/PECJ1W.

These built-in features enable developers to create their own Windows Runtime Components using managed code with C# and Visual Basic. Visual Studio 2012 provides a template for creating Windows Runtime Components from Visual Basic, C# and C++. These components can be consumed and called from any other language that supports the Windows Runtime, including JavaScript. For this reason, you must follow some specific rules to create a Windows Runtime Component in C#.

Playing by the Rules

In general, the rules for creating WinRT types in C# relate to any publicly visible types and members your component provides. The restrictions exist because the Windows Runtime Component must be bound by the WinRT type system. The full set of rules is listed in the MSDN Dev Center topic, “Creating Windows Runtime Components in C# and Visual Basic,” at bit.ly/OWDe2A. The fields, parameters and return values that you expose must all be WinRT types (it’s fine to expose .NET types that are automatically mapped to WinRT types). You can create your own WinRT types to expose provided those types, in turn, follow the same set of rules.

Another restriction is that any public classes or interfaces you expose can’t be generic or implement any non-WinRT interface. They must not derive from non-WinRT types. The root namespace for Windows Runtime Components must match the assembly name, which in turn can’t start with “Windows.” Public structures are also restricted to only have public fields that are value types. Polymorphism isn’t available to WinRT types, and the closest you can come is implementing WinRT interfaces; you must declare as sealed any classes that are publicly exposed by your Windows Runtime Component.

These restrictions might be reason to consider an alternative approach to integrating components within your apps, especially if you’re dealing with legacy code that would require significant refactoring. I’ll discuss possible alternative approaches later. The restrictions are important to ensure the Windows Runtime Components can function appropriately within the WinRT environment and can be referenced and called from all language environments, including C++ and JavaScript.

The Thumbnail Generator

A simple app will demonstrate how to create a managed Windows Runtime Component with C# and consume it from a Windows Store app built with C#, JavaScript or C++. The component accepts a reference to an image file passed by the WinRT IStorageFile interface. It then creates a 100x100 pixel thumbnail of the image and saves it to the Windows Store app’s local storage. It finally returns a URI that points to the thumbnail. The steps involved include:

  1. Create the solution in Visual Studio 2012.
  2. Build the Windows Runtime Component.
  3. Create the language-specific project in C#, JavaScript or C++.
  4. Reference the Windows Runtime Component.
  5. Set up the UI for each project to enable the user to pick an image.
  6. Display the image.
  7. Call the Windows Runtime Component.
  8. Display the thumbnail.

Create the Project and Solution

From within Visual Studio 2012, you begin by specifying your language of choice (in this case, C#) and choosing the Windows Store app templates. A template exists specifically for generating Windows Runtime Components. I selected this template and created a component called ThumbnailLibrary with a solution of the same name, as shown in Figure 2.

Creating the Windows Runtime Component Project
Figure 2 Creating the Windows Runtime Component Project

For this example, I created a single class called ThumbnailMaker. A private method returns a Task to asynchronously generate the thumbnail:

private static async Task<Uri> GenerateThumbnail(IStorageFile file)
{
}

The first step within the method is to open the file from storage and use the WinRT BitmapDecoder to decode the image stream:

using (var fileStream = await file.OpenReadAsync())
{
  var decoder = await BitmapDecoder.CreateAsync(fileStream);
}

Next, a file is created in the local storage for the app to hold the thumbnail. It will be named “thumbnail,” with the same extension as the source file. The option to generate a unique name will ensure that multiple thumbnails can be generated without overwriting previous operations:

var thumbFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(
  string.Format("thumbnail{0}", file.FileType),
  CreationCollisionOption.GenerateUniqueName);

An encoder is created from the decoded stream. It simply scales the bitmap to 100x100 pixels and then writes it to the file system:

using (var outputStream =
  await thumbFile.OpenAsync(FileAccessMode.ReadWrite))
{
  var encoder = await BitmapEncoder.CreateForTranscodingAsync(
    outputStream,
    decoder);
  encoder.BitmapTransform.ScaledHeight = 100;
  encoder.BitmapTransform.ScaledWidth = 100;
  await encoder.FlushAsync();
}

The last step is to build a URL that points to the file. The special ms-appdata prefix is used to reference the files in local storage. To learn more about how to reference content using URIs, read the MSDN Dev Center topic, “How to Reference Content,” at bit.ly/SS711o. Although the topic is for HTML and JavaScript, the convention used to access resources is the same regardless of what language option you’re using:

const string URI_LOCAL = "ms-appdata:///Local/{0}";
var storageUrl = string.Format(URI_LOCAL, thumbFile.Name);
return new Uri(storageUrl, UriKind.Absolute);

Windows Runtime Components written in C# can use any .NET functionality that’s allowed for the Windows Store app profile. As mentioned earlier, however, public types and interfaces must only expose WinRT types. Because Task isn’t a valid WinRT type, the public method for the component must expose the WinRT IAsyncOperation<T> type instead. Fortunately, an extension method exists to easily convert the .NET Task type to the WinRT IAsyncOperation type, as shown here:

public IAsyncOperation<Uri> GenerateThumbnailAsync(IStorageFile file)
{
  return GenerateThumbnail(file).AsAsyncOperation();            
}

With the component now complete, you can compile it to make it ready for consumption from Windows Store apps.

Under the Hood: Metadata

Build the Windows Runtime Component and then navigate to the output directory by right-clicking on the project name in the Solution Explorer and choosing “Open folder in Windows Explorer.” When you navigate to the bin/Debug subdirectory, you’ll find a metadata file has been generated for the component named ThumbnailLibary.winmd. If you open the file with ILDasm.exe, you’ll see an interface has been generated for the component with a return type of:

Windows.Foundation.IAsyncOperation<Windows.Foundation.Uri>

Those are the WinRT types that were mapped for the component. It’s possible to also inspect the metadata and see how the CLR projects WinRT types. Open the same metadata file with the special /project extension like this:

Ildasm.exe /project ThumbnailLibrary.winmd

The return type now appears as:

Windows.Foundation.IAsyncOperation<System.Uri>

Notice that the WinRT version of the URI is projected to the .NET equivalent. The method signature exposes all valid WinRT types for Windows Store apps to consume, but from managed code the types will appear as .NET classes. You can use the /project extension to inspect how projection will affect the signature of managed and unmanaged Windows Runtime Components.

Consume from C#

Consuming the component from C# should seem familiar because it’s no different than referencing a class library. Note that there’s no reason to build a Windows Runtime Component if your only target is other managed code. You simply reference the WinRT project and then consume the classes as you would from an ordinary C# class library. In the sample code, the CSharpThumbnails project has a reference to the ThumbnailLibrary. The XAML for the main page defines a button for the user to pick a photograph and contains two images to host the original image and the thumbnail version. Figure 3 shows the basic XAML markup.

Figure 3 XAML for Windows Store App Built with C#

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="Auto"/>
  </Grid.RowDefinitions>
  <TextBlock
    Text="Tap the button below to choose an image to generate a thumbnail."
    Style="{StaticResource BodyTextStyle}"
    Margin="12"/>
  <Button Content="Pick Image" Grid.Row="1" Margin="12"
    Click="Button_Click_1"/>
  <TextBlock Text="Thumbnail:" Style="{StaticResource BodyTextStyle}"
    Grid.Row="2" Margin="12"/>
  <Image x:Name="ThumbnailImage" HorizontalAlignment="Left" Stretch="None"
    Grid.Row="3" Margin="12"/>
  <TextBlock Text="Source Image:" Style="{StaticResource BodyTextStyle}"
    Grid.Row="4" Margin="12"/>
  <Image x:Name="SourceImage" HorizontalAlignment="Left" Stretch="None"
    Grid.Row="5" Margin="12"/>
</Grid>

The codebehind creates an instance of the WinRT FileOpenPicker component and configures it to browse images:

var openPicker = new FileOpenPicker
{
  ViewMode = PickerViewMode.Thumbnail,
    SuggestedStartLocation = PickerLocationId.PicturesLibrary
};
openPicker.FileTypeFilter.Add(".jpg");
openPicker.FileTypeFilter.Add(".jpeg");
openPicker.FileTypeFilter.Add(".png");

The picker is called and a simple dialog is displayed if no valid files are found:

var file = await openPicker.PickSingleFileAsync();
if (file == null)
{
  var dialog = new MessageDialog("No image was selected.");
  await dialog.ShowAsync();
  return;
}

The source image is then wired for display. The file is passed to the Windows Runtime Component to generate a thumbnail, and the URI passed back is used to set the thumbnail image for display:

 

using (var fileStream = await file.OpenReadAsync())
{
  SourceImage.Source = LoadBitmap(fileStream);
  var maker = new ThumbnailMaker();
  var stream = RandomAccessStreamReference
    .CreateFromUri(await maker.GenerateThumbnailAsync(file));
  var bitmapImage = new BitmapImage();
  bitmapImage.SetSource(await stream.OpenReadAsync());
  ThumbnailImage.Source = bitmapImage;
}

Figure 4shows the result of running this against a photo I took of a pumpkin I carved.

Windows Store Thumbnail App Built Using C#
Figure 4 Windows Store Thumbnail App Built Using C#

Consume from JavaScript

Unlike regular C# class libraries, Windows Runtime Components can be called from any language that’s supported for creating Windows Store apps (core Windows Runtime Components that are part of the OS can be called from desktop apps as well). To see this in action, you can create the thumbnail app using HTML and JavaScript. This project is called JavaScriptThumbnails in the accompanying sample code download. The first step is to create an empty app using the blank Windows Store template for apps built using JavaScript. Once the template has been created, you can use simple HTML markup to define the page using the existing default.html file:

<p>Tap the button below to choose an image to generate a thumbnail.</p>
<button id="pick">Pick Image</button>
<br/><br/>
<p>Thumbnail:</p>
<img id="thumbnail" src="images/logo.png" alt="Thumbnail"/>
<p>Source Image:</p>
<img id="sourceImage" src="images/logo.png" alt="Image"/>

Next, add a reference to the WinRT project (ThumbnailLibrary) just as you would to a regular C# project. Build the project so that you can use IntelliSense for the newly referenced component. You can reference the source code for the project to see the JavaScript equivalent for opening the file picker and selecting the image. To create an instance of the managed Windows Runtime Component, generate the thumbnail and display it to the user, use the following JavaScript:

var thumb = new ThumbnailLibrary.ThumbnailMaker();
thumb.generateThumbnailAsync(file).then(function (fileUrl) {
  var thumbImage = document.getElementById("thumbnail");
  thumbImage.src = fileUrl.rawUri;
  thumbImage.alt = thumbImage.src;
});

As you can see, the API call is almost identical to the one used in the C# project. Projection automatically changed the method signature from Pascal case to camel case (the call to generate the thumbnail begins with a lowercase character, as is the common convention in JavaScript code), and a special library called “promises” is used to handle the asynchronous nature of the code using a then or done statement. You can learn more about promises by reading the MSDN Dev Center topic, “Quickstart: Using Promises,” at bit.ly/OeWQCQ. The image tag supports URLs out of the box, so the URL passed back from the Windows Runtime Component is simply set directly to the src attribute on the image.

One important caveat for using managed components in JavaScript code is that you can’t debug JavaScript and managed code at the same time. If you need to debug your component, you must right-click the project and choose the Debugging tab, and then select a debugging option that includes managed code. This is shown in Figure 5.

Setting the Debug Options for a JavaScript Project
Figure 5 Setting the Debug Options for a JavaScript Project

Consume from C++

You can also consume managed Windows Runtime Components from native projects. C++ shares the same rendering engine as C#, so the CPlusPlusThumbnails project has the same XAML as the CSharpThumbnails project. The codebehind is different because the project uses the native C++ language option. C++ uses a special concurrency library to handle asynchronous operations. You can learn more about this library by reading the MSDN Dev Center topic, “Asynchronous Programming in C++,” at bit.ly/MUEqnR. The resulting code looks similar to the promises you saw in the JavaScript versions:

ThumbnailMaker^ maker = ref new ThumbnailMaker();
create_task(maker->GenerateThumbnailAsync(file)).then([this](Uri^ uri)
{
  RandomAccessStreamReference^ thumbnailStream =
    RandomAccessStreamReference::CreateFromUri(uri);
  create_task(thumbnailStream->OpenReadAsync()).then([this](
    IRandomAccessStream^ imageStream) {
    auto image = ref new BitmapImage();
    image->SetSource((IRandomAccessStream^)imageStream);
    ThumbnailImage->Source = image;
  });
});

When you run the app, you’ll find it looks and behaves identically to the C# version.

Understand the Cost

Creating Windows Runtime Components using managed languages is a powerful feature. This feature does come at a cost, however, and it’s important to understand the cost when you’re using it in projects. Windows Store apps built using native code don’t require the CLR to run. These apps may run directly in the Windows 8 environment. Similarly, apps developed using JavaScript also don’t require a dependency on the CLR. They rely on the Trident rendering engine and Chakra JavaScript engine (the same engines that drive Internet Explorer 10) to render HTML and CSS and interpret JavaScript code. Windows Store apps built with JavaScript may call native Windows Runtime Components directly, but when they call managed Windows Runtime Components, they take on a dependency to the CLR.

The code written for the managed Windows Runtime Component will be compiled just-in-time (JIT) when it’s first accessed by the CLR’s JIT compiler. This might cause some delay the first time it’s accessed. A precompilation service called NGen handles compiling modules installed on the device, but it can take up to a full day to eventually compile all of the modules in a package once it has been installed. The CLR also manages memory by performing garbage collection. The garbage collector (GC) divides the heap into three generations and collects only portions of the heap using an algorithm designed to optimize performance.

The GC might pause your app while it’s performing work. This often only introduces a slight delay that isn’t recognizable to the end user, and more intense garbage collection operations can often run in the background. If you have a large enough heap (when the managed portion of your code references hundreds of megabytes or more in memory objects), garbage collection might pause the app long enough for the user to perceive the lack of responsiveness.

Most of these considerations are already in place when you’re building a managed Windows Store app. Managed code does add new concerns when you’re adding it to a Windows Store app built with C++ or JavaScript. It’s important to recognize that your app will consume additional CPU and memory when you introduce managed components. It might also take a recognizable performance hit, depending on the component (although many apps take on managed references without any noticeable impact). The benefit is that you don’t have to worry about managing memory yourself and, of course, you can leverage legacy code and skills.

Alternatives for Managed Projects

If you’re building Windows Store apps using managed code (C# or Visual Basic), you have several alternatives to create Windows Runtime Components that don’t have the same restrictions. You can easily create reusable components using a simple C# class library. If the class library is built for Windows Store apps, you can reference the project from your own Windows Store app. The creation of a class library also removes the restrictions of having to expose only WinRT types and not being able to use features that aren’t part of the WinRT type system, such as generics.

Another alternative to consider is the Portable Class Library (PCL). This is a special type of class library that can be referenced from a variety of platforms without recompiling. Use this option if you have code you wish to share between other platforms—such as Windows Presentation Foundation, Silverlight and Windows Phone—and your Windows Store app. You can learn more about the PCL by reading my three-part blog series, “Understanding the Portable Library by Chasing ICommand,” at bit.ly/pclasslib.

When your component includes more than just code, you might consider creating an Extension SDK. This is a special form of SDK that Visual Studio 2012 can treat as a single item. The package might include source code, assets, files and even binaries, including Windows Runtime Components. You can also create design-time extensions to make it easier to consume and use your component from within Visual Studio 2012. Extension SDKs can’t be posted to the Windows Store because they’re not self-contained apps. You can learn more about Extension SDKs by reading the MSDN Library article, “How to: Create a Software Development Kit,” at bit.ly/L9Ognt.

When to Create Managed Windows Runtime Components

With so many possible alternatives, does it ever make sense to create Windows Runtime Components using managed code? Yes—but consider the following questions. The first question to ask is whether you need your components to be referenced from Windows Store apps written using JavaScript or native code using C++. If this isn’t the case, there’s no reason to use a Windows Runtime Component when class libraries and other options will work instead. If this is the case, you must create a Windows Runtime Component to be consumable from all of the available language options.

The next question is whether you should create your component in C++ or use managed code. There are a number of reasons to use managed code. One reason might be that your team is more experienced in C# or Visual Basic than in C++ and can leverage existing skills to build the components. Another reason might be that you have existing algorithms written in a managed language that will be easier to port if you keep the same language selection. There are some tasks that might be easier to write and maintain using managed languages and class libraries instead of using native code, and teams that are used to developing in managed languages will be far more productive.

Wrapping up, in this article you’ve learned you can create reusable Windows Runtime Components using managed C# and Visual Basic code. These components can be easily referenced and consumed from Windows Store apps written in any language, including JavaScript and C++. While it’s important to understand the rules for creating Windows Runtime Components and the impact of choosing to use managed code, this option provides a unique opportunity to use the language of your choice and leverage existing code to create components that can be consumed by all Windows Store apps.


Jeremy Likness *is a principal consultant for Wintellect LLC in Atlanta. He’s a three-year Microsoft Silverlight MVP and the author of several books, including the upcoming “Building Windows 8 Applications with C# and XAML” (Addison-Wesley Professional, 2012). Learn more online at bit.ly/win8design and follow his blog at csharperimage.jeremylikness.com.  *

Thanks to the following technical experts for reviewing this article: Layla Driscoll, Shawn Farkas, John Garland, Jeff Prosise and Jeffrey Richter