As Jaime Rodriguez detailed in April, Windows 8 Excellence Labs are made to help Metro developers to get a token which allows them to submit their application to the Windows Store with high confidence. I’m lucky enough to be part of this Microsoft effort and I hope meeting some of you soon :^)
A tool has been built to help Microsoft engineers to more easily check some basics of a Metro App such as implemented contracts or logos. This is a WPF Desktop application written in C# and its first task is to enumerate the installed Metro App packages.
I can imagine other scenari where you will certainly be interested in automatically checking that your application is well installed. This post will detail how a .NET developer could leverage WinRT from his Desktop application.
The first one allows you to use .NET types and the second one is the .NET view of the WinRT APIs. When you display the properties of the latter:
you end up in the C:\Program Files (x86)\Windows Kits\8.0\References\CommonConfiguration\Neutral\ folder where Windows.winmd waits for you. As explained by Martyn Lovell during his Lap around the Windows Runtime BUILD session, the WinRT team decided to keep the metadata format used by .NET assemblies to define their types and members.
This is great news because it means that you can use your preferred .NET decompiler to easily search and discover WinRT as any other managed API. However, the .winmd files do not contain any IL, you won’t be able to get a C# view of the code. For example, install ILSpy and load windows.winmd: all namespaces of WinRT are now visible and easily searchable by type or member name.
Note also that the EN subfolder contains the corresponding .XML file with the comments related to all types/members defined in Windows.winmd and ILSpy uses it to show these comments when available.
Among the hundreds of types define in Windows.winmd, here is what PackageManager provides as shown by ILSpy:
and especially the highlighted
The MSDN documentation provides a full page to describe “How to inventory packages” for all or one particular user, or for a given publisher.
But how to call this WinRT API from a Desktop application?
Well… simply by adding a reference to the project:
- Right-click on the References of the project and click Add Reference…
- Click the Browse button of the Browse entry on the left side of the dialog
- Enter C:\Program Files (x86)\Windows Kits\8.0\References\CommonConfiguration\Neutral\ into the File name textbox
- You won’t see any file because by default only .dll, .tlb, .olb, .ocx, .exe and .manifest are listed. So, type *.winmd and press enter to see Windows.winmd that you select before pressing the Add button.
- Dismiss the main dialog by pressing the OK button
Once Windows.winmd is added to the project references, type
PackageManager and CTRL+. to trigger the auto-completion that proposes you to add a
using Windows.Management.Deployment namespace statement:
Exactly the same as with any other .NET assembly; neat isn’t it?
How to list installed Metro packages
On the same machine, different users will deploy different Metro App packages. Each user will see and launch only Apps that he has installed (see the Under the hood: installation and updates for Metro style BUILD session for more details).
Microsoft provides several C# code samples to enumerate Metro App packages either by user, for all users, or by publisher.
- Enumerate app packages by user SID sample
- Enumerate app packages sample
- Enumerate app packages by name and publisher sample
All these projects have a reference to Windows.winmd in order to access the
Windows.Management.Deployment.PackageManager methods. The sample which enumerates App packages for a given user relies on his corresponding Security ID. However, it is difficult to provide the SID as a command line argument… Hopefully, the SID of the current user is easily return by
IEnumerable sequence is perfect to use with a foreach statement in which the details of each
Package are printed out.
Package type is defined in the
Windows.ApplicationModel namespace. The type
PackageId of its
Id property contains the name of the package with other interesting details such as processor architecture, publisher or version.
InstalledLocation property is an instance of
StorageFolder that exposes a handful
Note that if you are downloading Metro App samples and run/debug them, the corresponding compiled packages are deployed on the machine and will be listed by
FindPackagesForUser. However, it might happens that you delete the sample because you don’t need it anymore: expect to catch a
System.IO.FileNotFoundException in that case.
- App packages and deployment (Metro style apps)
- How to inventory packages
- “A Lap around the Windows Runtime” BUILD session
- “Under the hood: installation and updates for Metro style apps” BUILD session
I hope this helps