Introduction to the Windows Runtime - Build Windows® 8 Apps with Microsoft® Visual C#® and Visual Basic® Step by Step (2013)

Build Windows® 8 Apps with Microsoft® Visual C#® and Visual Basic® Step by Step (2013)

Chapter 5. Introduction to the Windows Runtime

After completing this chapter, you will be able to

§ Understand the architecture of the Windows Runtime (WinRT).

§ Leverage the new Windows 8 APIs across multiple languages.

§ Create custom WinMD libraries.

This chapter provides an introduction to the Windows Runtime application programming interfaces (APIs), which are the new APIs that sit at the very base of every Microsoft Windows 8 app.

Overview of the Windows Runtime

Microsoft Windows, since its earliest version, has always provided developers with libraries and APIs to interact with the operating system. However, before the release of Windows 8, those APIs and libraries were often complex and painful to use. Moreover, while working in .NET Framework using C# or VB.NET, you often had to rely on COM (Component Object Model) Interop and Win32 interoperability via P/Invoke (Platform Invoke) in order to directly leverage the operating system. For example, consider Example 5-1.

Example 5-1. A sample code excerpt leveraging Win32 in C#

[DllImport("avicap32.dll", EntryPoint="capCreateCaptureWindow")]

static extern int capCreateCaptureWindow(

string lpszWindowName, int dwStyle,

int X, int Y, int nWidth, int nHeight,

int hwndParent, int nID);

[DllImport("avicap32.dll")]

static extern bool capGetDriverDescription(

int wDriverIndex,

[MarshalAs(UnmanagedType.LPTStr)] ref string lpszName,

int cbName,

[MarshalAs(UnmanagedType.LPTStr)] ref string lpszVer,

int cbVer);

This sample C# code imports a couple of Win32 APIs into the .NET world to leverage the video capture features of your PC. As you can see, the code is not tricky and the syntax can be prone to easy errors.

Microsoft acknowledged the complexity of the previously existing scenario and made a huge investment in Windows 8 and the Windows Runtime (WinRT) to simplify the interaction with the native operating system. In fact, the WinRT is a set of fresh, new APIs that were reimagined from the developer perspective to make easy, simple, and fast what previously was too complex. Moreover, the WinRT is built so that it supports the idea of developing Windows 8 apps with many of the available programming languages and environments, such as HTML5/WinJS, CLR, and C++.

Example 5-2 shows the same code used in Example 5-1, but rewritten using WinRT and C# instead.

Example 5-2. A sample code excerpt leveraging WinRT in C#

using Windows.Media.Capture;

var camera = new CameraCaptureUI();

camera.PhotoSettings.CroppedAspectRatio = new Size(4, 3);

var file = await camera.CaptureFileAsync(CameraCaptureUIMode.Photo);

if (file != null)

{

var bitmap = new BitmapImage() ;

bitmap.SetSource(await file.OpenAsync(FileAccessMode.Read));

Photo.Source = bitmap;

}

The preceding code illustrates how the syntax is clearer and easier to write, as well as easier to read and maintain in the future, when leveraging WinRT. In this last example, Photo is a XAML Image control.

As mentioned before, if you prefer to write code using WinJS and HTML5, the code will be similar to the C# version, as you can see in Example 5-3.

Example 5-3. Sample code excerpt leveraging WinRT in WinJS

var camera = new capture.CameraCaptureUI();

camera.captureFileAsync(capture.CameraCaptureUIMode.photo)

.then(function (file) {

if (file != null) {

media.shareFile = file;

}

});

Basically, WinRT is a rich set of APIs built upon the Windows 8 operating system that provides direct and easy access to all the main primitives, devices, and capabilities for any language available for developing Windows 8 apps. WinRT is available only for building Windows 8 apps. Its main goal is to unify the development experience of building a Windows 8 app, regardless of which programming language you choose.

Figure 5-1 shows the overall architecture of WinRT.

High-level architecture of WinRT.

Figure 5-1. High-level architecture of WinRT.

WinRT sits on top of the Windows Runtime core engine, which is a set of C++ libraries that bridge WinRT with the underlying operating system. On top of the WinRT core, there is a rich set of specific libraries and types that interact with the various tools and devices available in any Windows 8 app. For example, there is a library that works with the network and another that reads and writes from the storage (local or remote). There is a set of pickers to pick up items (files, pictures, and so on.) and there are a bunch of classes to leverage media services, and so on. All these types and libraries are defined in a structured set of namespaces and are described by a set of metadata called Windows Metadata (WinMD). All metadata information is based on a new file format, which is built upon the Common Language infrastructure (CLI) metadata definition language (ECMA-335).

As already stated, the WinRT core engine is written in C++ and internally leverages a proprietary set of data types. For example, there is the notion of HSTRING, which is the name of the type representing a text value in WinRT. Also, there are numeric types like INT32 and UINT64, enumerable collections represented by IVector<T>, enums, structures, runtime classes, and so on.

In order to be able to consume all this stuff from any supported programming language, WinRT provides a projection layer that shuttles types and data between WinRT and the target language. For example, the WinRT HSTRING type will be translated into a System.String of .NET for a common language runtime (CLR) app, or to a Platform::String for a C++ app.

Next to this layered architecture there is a “Runtime Broker,” which acts as a bridge between the operating system and the host executing Windows 8 apps, whether those are CLR, HTML5/WinJS, or C++ apps.

To better understand the architecture and philosophy behind WinRT, in the following procedure your code will consume WinRT from a CLR Windows 8 app.

Using WinRT from a CLR Windows 8 app

In this procedure, you will use the WinRT Camera APIs to capture an image from a C# Windows 8 app.

1. Create a new Application project. To do that, open Microsoft Visual Studio 2012, and from the File menu, select New Project (the sequence can be File | New | Project for full featured versions of Visual Studio). Choose Visual C# in the Templates tree and then Windows Store from the list of installed templates. Then select Blank App (XAML) from the list of available projects.

Select version 4.5 as the target .NET Framework version for your new project (this is not necessary in Visual Studio Express edition).

2. Name the new project WinRTFromCS, and then choose a location on your file system and accept the default solution name. When you have finished, click OK.

3. As you saw in Chapter 3, the Windows Store Application template provides a default page (MainPage.xaml), an application entry point in the App class (App.xaml.cs), a default application description and a declaration in the Package.appxmanifest file, as well as four default images representing logos and a splash screen.

4. In Solution Explorer, double-click MainPage.xaml.

This file contains the layout of the user interface. The window, named Design View, shows two different views of this file: the Design and the XAML view.

5. Scroll down the MainPage.xaml source code and insert a Button control inside a StackPanel control, as illustrated in the bolded lines of the following code excerpt.

6. <Page x:Class="WinRTFromCS.MainPage"

7. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

8. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

9. xmlns:local="using:WinRTFromCS"

10. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

11. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

12. mc:Ignorable="d">

13. <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">

14. <StackPanel>

15. <Button Click="UseCamera_Click" Content="Use Camera" />

16. </StackPanel>

17. </Grid>

</Page>

18.Right-click the UseCamera_Click attribute of the Button element and select Navigate To Event Handler.

19.Replace the event handler code with the following code.

20.private async void UseCamera_Click(object sender, RoutedEventArgs e)

21.{

22. var camera = new Windows.Media.Capture.CameraCaptureUI();

23. var photo = await camera.CaptureFileAsync(

24. Windows.Media.Capture.CameraCaptureUIMode.Photo);

}

Notice the async keyword (which will be explained in Chapter 8) and the two lines of code inside the event handler that instantiate an object of type CameraCaptureUI and invoke its CaptureFileAsync method.

25.Insert a breakpoint at the first line of code (the one starting with var camera = ...) and start debugging the app. When the breakpoint is reached the call stack window reveals that the app is called by External Code, which is native code.

image with no caption

If you try to step into the code of the CameraCaptureUI type constructor you will see that it is not possible in managed code because the type is defined in WinRT, which is unmanaged.

26.Stop the app by stopping the debugger or pressing Alt-F4 to close the app window.

Using WinRT from a C++ Windows 8 app

In this procedure, you will use the WinRT Camera APIs to capture an image from a C++ Windows 8 app. First, you need to create a fresh app, using C++ this time.

1. Create a new Application project. To do that, open Visual Studio 2012, and from the File menu, select New Project (the sequence can be File | New | Project for full featured versions of Visual Studio). Choose Visual C++ from the Templates tree and then Windows Store from the list of installed templates. Then choose Blank App (XAML) from the list of available projects.

2. Name the new project WinRTFromCPP, then choose a location on your file system and leave the provided solution name. When you have finished, click OK.

3. In Solution Explorer, double-click MainPage.xaml.

4. Scroll down the MainPage.xaml source code and insert a Button control inside a StackPanel control, as illustrated in the bold lines of the following code excerpt.

5. <Page x:Class="WinRTFromCPP.MainPage"

6. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

7. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

8. xmlns:local="using:WinRTFromCPP"

9. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

10. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

11. mc:Ignorable="d">

12. <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">

13. <StackPanel>

14. <Button Click="UseCamera_Click" Content="Use Camera" />

15. </StackPanel>

16. </Grid>

</Page>

17.Right-click the UseCamera_Click attribute of the Button element and select Navigate To Event Handler.

18.Replace the event handler code with the following code.

19.void WinRTFromCPP::MainPage::UseCamera_Click(Platform::Object^ sender,

20. Windows::UI::Xaml::RoutedEventArgs^ e) {

21. auto camera = ref new Windows::Media::Capture::CameraCaptureUI();

22. camera->CaptureFileAsync(Windows::Media::Capture::CameraCaptureUIMode::Photo);

}

23.Insert a breakpoint at the first line of code (the one starting with auto camera = ...) and start debugging the app. As you can see, you will be able to step into the native code of the CameraCaptureUI constructor, as well as into the code of the CaptureFileAsync method.

24.Stop the app by stopping the debugger or pressing Alt-F4 to close it.

By experimenting with this exercise you may also notice that the names of the types, as well as the names of the methods and enums, are almost the same in C# and in C++. Nevertheless, each individual language has its own syntax, code casing, and style. However, through this procedure, you have gained hands-on experience with the real nature of WinRT: a multi-language API that adapts its syntax and style to the host language and maintains a common set of behavior capabilities under the covers. What you have just seen is the result of the language projection layer defined in the architecture of WinRT.

To take this exercise one step further, you can create the same example you did in C# and C++ using HTML5/WinJS. If you do that, you will see that the code casing will adapt to the JavaScript syntax.

Windows Runtime under the covers

The language projection of WinRT is based on a set of new metadata files, called Windows Metadata (WinMD). By default, those files are stored under the path <OS Root Path>\System32\WinMetadata, where <OS Root Path> should be replaced with the Windows 8 root installation folder (normally C:\Windows). The following is a list of the default contents of the WinMD folder.

§ Windows.ApplicationModel.winmd

§ Windows.Data.winmd

§ Windows.Devices.winmd

§ Windows.Foundation.winmd

§ Windows.Globalization.winmd

§ Windows.Graphics.winmd

§ Windows.Management.winmd

§ Windows.Media.winmd

§ Windows.Networking.winmd

§ Windows.Security.winmd

§ Windows.Storage.winmd

§ Windows.System.winmd

§ Windows.UI.winmd

§ Windows.UI.Xaml.winmd

§ Windows.Web.winmd

Note that the folder includes a Windows.Media.winmd file, which contains the definition of the CameraCaptureUI type that you used in the previous exercise.

You can inspect any WinMD file using the Intermediate Language Disassembler (ILDASM) tool available in the Microsoft .NET SDK, which ships with Microsoft Visual Studio 2012 and that you can also download as part of the Microsoft .NET Framework SDK. For example, Figure 5-2shows the ILDASM tool displaying the content outline of the Windows.Media.winmd file, which contains the definition of the CameraCaptureUI type that you used in the previous exercise.

The ILDASM tool showing part of the Windows.Media.winmd file, which contains the definition of the CameraCaptureUI type.

Figure 5-2. The ILDASM tool showing part of the Windows.Media.winmd file, which contains the definition of the CameraCaptureUI type.

At the top there is a file MANIFEST, which defines the name, version, signature, and dependencies of the current WinMD file. Moreover, there is a hierarchy of namespaces grouping various types. Each single type defines a class from the WinRT perspective. In Figure 5-3, you can clearly identify the CaptureFileAsync method (CameraCaptureUI type) you used in the previous example. By double-clicking the method in the outline, you can see its definition, which is not the source code of the method but rather the metadata mapping it to the native library that will be leveraged under the cover. In the following code excerpt, you can see the metadata definition of the CaptureFileAsync method defined for the CameraCaptureUI type.

.method public hidebysig newslot virtual final

instance class [Windows.Foundation]Windows.Foundation.IAsyncOperation'1<class

[Windows.Storage]Windows.Storage.StorageFile>

CaptureFileAsync([in] valuetype Windows.Media.Capture.CameraCaptureUIMode mode) runtime

managed {

.override Windows.Media.Capture.ICameraCaptureUI::CaptureFileAsync

} // end of method CameraCaptureUI::CaptureFileAsync

The language projection infrastructure will translate this neutral definition into the proper format for the target language.

Whenever a language needs to access a WinRT type, it will inspect its definition through the corresponding WinMD file and will use the IInspectable interface, which is implemented by any single WinRT type. The IInspectable interface is an evolution of the already well-known IUnknowninterface declared many years ago in the COM world.

Figure 5-3 shows a graphical schema of the structure of every single WinRT object.

WinRT object schema.

Figure 5-3. WinRT object schema.

First, there is a type declaration inside the registry of the operating system. All the WinRT types are registered under the path HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsRuntime\ActivatableClassId.

For example, the CameraCaptureUI type is defined under the following path:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsRuntime\ActivatableClassId\Windows.Media.Capture.

CameraCaptureUI

The registry key contains some pertinent information, including the activation type (in process or out of process), as well as the full path of the native dynamic-link library (DLL) file containing the implementation of the target type.

The type implements the IInspectable interface, which provides the following three methods:

§ GetIids. Gets the interfaces that are implemented by the current WinRT class

§ GetRuntimeClassName. Gets the fully qualified name of the current WinRT object

§ GetTrustLevel. Gets the trust level of the current WinRT object

By querying the IInspectable interface, the language projection infrastructure of WinRT will translate the type from its original declaration into the target language that is going to consume the type.

As illustrated in Figure 5-4, the projection occurs at compile time for a C++ app consuming WinRT, and it will produce native code that will not need any more access to the metadata. In the case of a CLR app (C#/VB), it happens during compilation into IL code, as well as at runtime through a runtime callable wrapper. However, the cost of communication between CLR and the WinRT metadata is not so different than the cost of talking with the CLR metadata in general. Lastly, in the case of an HTML5/WinJS app it will occur at runtime through the Chakra engine.

How data moves between C++, the CLR, HTML/WinJS, and WinRT.

Figure 5-4. How data moves between C++, the CLR, HTML/WinJS, and WinRT.

The overall architecture of WinRT is also versioning compliant. In fact, every WinRT type will be capable of supporting a future version of the operating system and of the Windows Runtime engine by simply extending the available interfaces implemented and providing the information about the new extensions through the IInspectable interface.

Windows Runtime design requirements

To support the architecture of WinRT and the language projection infrastructure, every Windows 8 app—regardless of the programming language used to write it—runs in a standard code execution profile that is based on a limited set of capabilities. To accomplish this goal, the WinRT product team defined the minimum set of APIs needed to implement a Windows 8 app. For example, the Windows 8 app profile has been deprived of the entire set of console APIs, which are not needed in a Windows 8 app. The same happened to ASP.NET, for instance—the list of .NET types removed is quite long. Moreover, the WinRT product team decided to remove all the old-style, complex, and/or dangerous APIs and instead provide developers with a safer and easier working environment. As an example, to access XML nodes from a classic .NET application, you have a rich set of APIs to choose from (XML Document Object Model, Simple API for XML, LINQ to XML in .NET, and so on). The set also depends on which programming language you are using. In contrast, in a Windows 8 app written in CLR (C#/VB) you have only the LINQ to XML support, while the XML Document Object Model has been removed.

Furthermore, considering a Windows 8 app is an application that can execute on multiple devices (desktop PCs, tablets, ARM-based devices, and Windows Phone 8 mobile phones), all the APIs specific to a particular operating system or hardware platform have been removed.

The final result is a set of APIs that are clear, simple, well-designed, and portable across multiple devices. From a .NET developer perspective, the Windows 8 app profile is a .NET 4.5 profile with a limited set of types and capabilities, which are the minimum set useful for implementing a real Windows 8 app.

Consider this: the standard .NET 4.5 profile includes more than 120 assemblies, containing more than 400 namespaces that group more than 14,000 types. In contrast, the Windows 8 app profile includes about 15 assemblies and 70 namespaces that group only about 1,000 types.

The main goals in this profile design were to:

§ Avoid duplication of types and/or functionalities.

§ Remove APIs not applicable to Windows 8 apps.

§ Remove badly designed or legacy APIs.

§ Make it easy to port existing .NET applications to Windows 8 apps.

§ Keep .NET developers comfortable with the Windows 8 app profile.

Figure 5-5 shows a diagram of the main .NET APIs available in a Windows 8 app.

.NET APIs available to a Windows 8 application.

Figure 5-5. .NET APIs available to a Windows 8 application.

For example, the Windows Communication Foundation (WCF) APIs exist, but you can use WCF only to consume services, therefore leveraging a reduced set of communication bindings. You cannot use WCF in a Windows 8 app to host a service—for security reasons and for portability reasons.

Creating a WinMD library

The previous sections contained some information about the WinRT architecture and the WinMD infrastructure—which allows the language projection of WinRT to make a set of APIs available to multiple programming languages. In this section, you will learn how to create a library of APIs of your own, making that library available to all other Windows 8 apps through the same projection environment used by WinRT.

Internally, the WinRT types in your component can use any .NET Framework functionality that’s allowed in a Windows 8 app. Externally, however, your types must adhere to a simple and strict set of requirements.

§ The fields, parameters, and return values of all the public types and members in your component must be WinRT types.

§ Public structures may not have any members other than public fields, and those fields must be value types or strings.

§ Public classes must be sealed (NotInheritable in Visual Basic). If your programming model requires polymorphism, you can create a public interface and implement that interface on the classes that must be polymorphic. The only exceptions are XAML controls.

§ All public types must have a root namespace that matches the assembly name, and the assembly name must not begin with “Windows.”

In the following exercise, you will create a WinMD library and share it across all the languages supported by Windows 8 apps.

Using C# to create a WinMD library sharable with C++ and HTML5/WinJS

1. Create a new Windows Runtime Component project. To do that, open Visual Studio 2012, and from the File menu, select New Project. Choose Visual C# from the Templates tree and then Windows Store from the list of installed templates. Then choose Windows Runtime Component from the list of available projects

2. Select version 4.5 as the Microsoft .NET Framework target version for your new project.

3. Name the new project WinMDCSLibrary, and then choose a location on your file system and leave the provided solution name. When you have finished, click OK.

4. Right-click the project icon in the Solution Explorer and choose Properties. The project Output Type is Windows Runtime Component, which means that the project will create not only a DLL, but also a WinMD file for sharing the library with any Windows 8 app written with any language.

image with no caption

5. Close the Project Properties window.

6. In the Solution Explorer, right-click the Class1.cs file and select Rename. Enter the new name SampleUtility.cs and when prompted by Visual Studio, confirm that you want to also rename the class and not just the file.

7. Add the following using statement at the beginning of the file, before the class declaration.

using System.Text.RegularExpressions;

8. Insert the following code into the class file.

9. public Boolean IsMailAddress(String email)

10.{

11. Regex regexMail = new Regex(@"\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b");

12. return(regexMail.IsMatch(email));

}

13.Build the project by right-clicking the project icon in the Solution Explorer and choosing Build.

14.Check the output by right-clicking the project icon in the Solution Explorer and choosing Open Folder In File Explorer.

15.Browse to the bin\Debug subfolder.

16.As you can see in the output folder, there is a WinMDCSLibrary.winmd file.

Open the file with ILDASM, just to check its content and to see that the file defines the WinMDCSLibrary.SampleUtility class.

Next you will consume this C#-based Windows Runtime Component from C++.

Consuming a WinMD library created with C# from C++

1. Open the solution defined in the previous exercise, if it is not already open.

2. Add a new Application project. To do that, from the File menu, select Add New Project. Choose Visual C++ from the Templates tree and then Windows Store from the list of installed templates. Finally, choose Blank App (XAML) from the list of available projects.

3. Name the new project WinMDCPPConsumer, and then choose a location on your file system. When you have finished, click OK.

4. In Solution Explorer, right-click the WinMDCPPConsumer project and select the References menu item.

5. In the WinMDCPPConsumer Property Pages window, select Add New Reference.

6. In the left pane of the Add Reference window, select Solution, and then select Projects.

7. In the right pane, select the WinMDCSLibrary project and click OK twice.

image with no caption

8. In Solution Explorer, double-click the MainPage.xaml file in the WinMDCPPConsumer project.

This file contains the layout for the user interface. The window, named Design View, shows two different views of this file: the Design view and the XAML view.

9. Scroll down the MainPage.xaml source code and insert a Button control inside a StackPanel control, as illustrated in the bold lines of code in the following excerpt.

10.<Page x:Class="WinRTFromCS.MainPage"

11. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

12. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

13. xmlns:local="using:WinRTFromCS"

14. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

15. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

16. mc:Ignorable="d">

17. <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">

18. <StackPanel>

19. <Button Click="ConsumeWinMD_Click" Content="Consume WinMD Library" />

20. </StackPanel>

21. </Grid>

</Page>

22.Right-click the ConsumeWinMD_Click attribute of the Button element and select Navigate To Event Handler.

23.Replace the event handler code with the following code.

24.void WinMDCPPConsumer::MainPage::ConsumeWinMD_Click(Platform::Object^ sender,

25. Windows::UI::Xaml::RoutedEventArgs^ e) {

26. auto utility = ref new WinMDCSLibrary::SampleUtility();

27. bool result = utility->IsMailAddress("paolo@devleap.com");

}

Build the whole solution.

28.Place a breakpoint in the IsMailAddress method of WinMDCSLibrary and start the C++ project in debug mode, configuring “Mixed (Managed and Native)” in the debugging properties of the WinMDCPPConsumer project.

image with no caption

When executing the application, you will see that the debugger will step into the C# code starting from the C++ code.

29.After debugging, close the sample C++ app by pressing Alt-F4 or stopping the app execution in Visual Studio.

Do not close Visual Studio.

Next, you’ll consume the same component in HTML5/WinJS.

Consuming a WinMD library created with C# from HTML5/WinJS

1. Open the C# solution you defined previously, if it’s not already open.

2. Add a new HTML5/WinJS Application project. To do that, from the File menu, select Add New Project. Choose JavaScript from the Templates tree and then Windows Store from the list of installed templates. Finally, choose Blank App from the list of available projects.

3. Name the new project WinMDJSConsumer, and then choose a location on your file system and accept the default solution name. When you have finished, click OK.

4. In the Solution Explorer, right-click the References folder of the WinMDJSConsumer project and select Add Reference.

5. In the left pane of the Reference Manager window, select Solution and then select Projects.

6. In the right pane of the Reference Manager window, select the WinMDCSLibrary project and click OK.

image with no caption

7. In Solution Explorer, double-click the Default.html file of the WinMDJSConsumer project.

This file contains the layout for the user interface.

8. Replace the HTML body of the Default.html page with the following code:

9. <body>

10. <p><button id="consumeWinMDLibrary">Consume WinMD Library</button></p>

</body>

11.Open the Default.js file, which is in the js folder of the project, and place the following event handler inside the file, just before the app.start() method invocation.

12.function consumeWinMD(eventInfo) {

13. var utility = new WinMDCSLibrary.SampleUtility();

14. var result = utility.isMailAddress("paolo@devleap.com");

}

Notice that the case of the IsMailAddress method, defined in C#, has been translated into isMailAddress in JavaScript thanks to the language projection infrastructure provided by WinRT.

15.Next, insert the following lines of code into the function associated with the app.onactivated event, just before the end of the if statement.

16.// Retrieve the button and register the event handler.

17.var consumeWinMDLibrary = document.getElementById("consumeWinMDLibrary");

consumeWinMDLibrary.addEventListener("click", consumeWinMD, false);

Here’s how the complete code of the Default.js file should look after you have made the edits.

// For an introduction to the Blank template, see the following documentation:

// http://go.microsoft.com/fwlink/?LinkId=232509

(function () {

"use strict";

WinJS.Binding.optimizeBindingReferences = true;

var app = WinJS.Application;

var activation = Windows.ApplicationModel.Activation;

app.onactivated = function (args) {

if (args.detail.kind === activation.ActivationKind.launch) {

if (args.detail.previousExecutionState !==

activation.ApplicationExecutionState.terminated) {

// TODO: This application has been newly launched. Initialize

// your application here.

} else {

// TODO: This application has been reactivated from suspension.

// Restore application state here.

}

args.setPromise(WinJS.UI.processAll());

// Retrieve the button and register our event handler.

var consumeWinMDLibrary = document.getElementById("consumeWinMDLibrary");

consumeWinMDLibrary.addEventListener("click", consumeWinMD, false);

}

};

app.oncheckpoint = function (args) {

// TODO: This application is about to be suspended. Save any state

// that needs to persist across suspensions here. You might use the

// WinJS.Application.sessionState object, which is automatically

// saved and restored across suspension. If you need to complete an

// asynchronous operation before your application is suspended, call

// args.setPromise().

};

function consumeWinMD(eventInfo) {

var utility = new WinMDCSLibrary.SampleUtility();

var result = utility.isMailAddress("paolo@devleap.com");

}

app.start();

})();

18.Build the solution.

19.Place a breakpoint in the IsMailAddress method of WinMDCSLibrary and start the HTML5/WinJS project in debug mode, configuring “Mixed (Managed and Native)” in the debugging properties of the WinMDJSConsumer project.

image with no caption

As the code executes, the debugger will step into the C# code starting from the JavaScript code.

20.After debugging, close the sample HTML5/WinJS app by pressing Alt-F4 or by stopping the execution in Visual Studio.

Windows Runtime app registration

Whenever you create a Windows 8 app and launch it through the Visual Studio 2012 debugger, you’ll find that it is placed as a Tile into the Start screen of Windows 8. For example, if you followed all the previous exercises, your Windows 8 Start screen will have the tiles shown in Figure 5-6.

Tiles for the sample project in the Windows 8 Start screen.

Figure 5-6. Tiles for the sample project in the Windows 8 Start screen.

In fact, every single time you execute a project from Visual Studio 2012, it automatically adds your app to the Start screen. Under the covers, your app is registered into the Windows Registry, using some information defined in the Package.appxmanifest file available in your project. If you double-click that file, for example in the WinMDJSConsumer project you defined in the last exercise, you will be prompted with a graphical editor/designer as in Figure 5-7, which shows the Packaging tab of the designer.

Packaging tab of the designer in Visual Studio 2012.

Figure 5-7. Packaging tab of the designer in Visual Studio 2012.

The Package name property contains the unique name used to identify the package on any target device. You should provide a human-friendly name to this property instead of using the default GUID generated by Visual Studio 2012. In addition, the Package display name will be shown in the app’s tile on the Start screen. In the designer, you can supply a logo, version number, and the publisher display name as additional information used to describe the package and the app better.

When you register (in this case, execute an app for the first time from Visual Studio 2012) a Windows 8 app, the system reads the packaging information and writes some information into the Windows Registry. Execute the following instructions to better understand what happens under the cover.

1. Supply the value WinMDJSConsumer to the Package name property of the WinMDJSConsumer project in the Package.appxmanifest file.

2. Execute the WinMDJSConsumer Windows 8 app.

3. Close the app by pressing Alt-F4.

4. Open the Registry Editor by pressing Windows+Q and typing Regedit, select the Registry Editor tool on the search result page and when asked, execute it with elevated privileges.

Under the HKEY_CLASSES_ROOT\Extensions\ContractId\Windows.Launch key you will find a sub-key named PackageId. That key contains a sub-key called WinMDJSConsumer_1.0.0.0_x86__xnwnzdjs5148r, which is the name of the package, followed by its build version, the target platform, and an alphanumeric code describing the publisher.

That key will, in turn, contain a sub-key named ActivatableClassId, which defines the sub-key app (for CLR and C++ apps) or App.wwa (for HTML5/WinJS apps).

Under HKEY_CURRENT_USER\Software\Classes\ActivatableClasses\Package there will be a corresponding ActivatableClasses key that will define the packages, under the Package sub-key. Figure 5-8 shows the registry outline for this section if you executed the apps in the previous exercises.

The Registry editor, showing entries made by registering the example apps in this chapter.

Figure 5-8. The Registry editor, showing entries made by registering the example apps in this chapter.

When you start a new app instance or resume an already executing instance by clicking or tapping its tile in the Start screen, the operating system will read the server sub-key of the package defined in the ActivatableClasses and will locate the path of the process to execute from the ExePathkey. Notice that the WinMDJSConsumer App has an ExePath corresponding to the standard HTML5 app host, which is C:\Windows\syswow64\wwahost.exe.

In contrast, the WinMDCPPConsumer App has an ExePath value of <Path of your exercises>\AppX\WinMDCPPConsumer.exe.

Both apps will have a key named CustomAttributes, under the App key that is a child of the ActivatableClassId sub-key of each package.

The CustomAttributes key contains an AppObject.EntryPoint string value, which defines the entry point of the app. For the C++ App that assumes the value WinMDCPPConsumer.App (the main class). But the HTML5/WinJS App will have a value of Default.html (the default HTML page).

Summary

In this chapter, you have seen what the Windows Runtime is, how it works, and a high-level view of its architecture. You also learned what a Windows 8 app profile is, and how to create a custom Windows Runtime Component library that you or other developers can consume from multiple languages, all while leveraging the language projection features of WinRT.

Quick reference

To

Do this

Get a picture from the camera of a Windows 8 device

Using C# code, instantiate the CameraCaptureUI class and invoke the CaptureFileAsync method.

Inspect the content of a WinMD file

Use the ILDASM tool available in the .NET Framework SDK.

Debug a solution based on a mixture of CLR and C++ code

Configure the debugging options to support “Mixed (Managed and Native)” debug.

Understand what apps are registered in the Start screen of Windows 8

Inspect the Windows Registry under the key HKEY_CLASSES_ROOT\Extensions\ContractId\Windows.Launch.