How to call WinRT APIs from C# Desktop applications – list the installed Metro packages

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.

How to see the WinRT APIs in VS/.NET Decompiler
When you create a blank Metro App in C# with VS 2012 RC, two references are added to the project:

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 FindPackagesForUser method.
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:

  1. Right-click on the References of the project and click Add Reference…
  2. Click the Browse button of the Browse entry on the left side of the dialog
  3. Enter C:\Program Files (x86)\Windows Kits\8.0\References\CommonConfiguration\Neutral\ into the File name textbox
  4. 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.
  5. 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.

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 WindowsIdentity.GetCurrent().User.Value.
The return IEnumerable sequence is perfect to use with a foreach statement in which the details of each Package are printed out.

The 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.
Its InstalledLocation property is an instance of StorageFolder that exposes a handful Path property.
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.

Here is the source code of the Console application:

References

Download the solution

I hope this helps

This entry was posted in .NET, C#, Metro, Release Preview, WinRT and tagged , , , , , . Bookmark the permalink.

36 Responses to How to call WinRT APIs from C# Desktop applications – list the installed Metro packages

  1. Pingback: Windows 8 Developer Links – 2012-06-13 | Dan Rigby

  2. Pingback: How to call WinRT APIs from C# Desktop applications – list the installed Metro packages

  3. Pingback: Investigating BCL differences between .NET and Metro/WinRT | Anything about WinRT

  4. Mitch Denny says:

    This is cool. Have you found a way to initiate share operations from a desktop application?

  5. Hi Mitch, I don’t know but I fear it won’t work outside a Metro App because you get the DataTransferManager from the current view that is valid only in a Metro App context.

    • Mitch Denny says:

      Hi Christophe,

      I had tried to use DataTransferManager directly and gotten a few errors. What you are saying confirms what I saw there. Thanks. Shame – there could be some interesting desktop-metro sharing scenarios if they had opened that up.

      What got me thinking it was possible was that in the Developer Preview you could share a screenshot from the desktop. That might have been more to do with the process being explorer.exe though.

  6. Ashok kumar says:

    I have created a .winmd file using VS 2012 RC. I want to use that .winmd in another metro style app, my question is where to keep that .winmd file in a common place while using or packaging my metro style app.

    • Hi Ashok,

      I don’t know if it is possible to share the same .winmd file on disk between two Metro Apps but I would not be optimistic. You reference the same .winmd in the two projects but it gets copied in the two packages that then get deployed in two different locations on disk.

      Sorry if this is not a good news…

  7. ashwin says:

    Keep getting this error with the above code.. any ideas??

    foreach statement cannot operate on variables of type ‘System.Collections.Generic.IEnumerable`1’ because ‘System.Collections.Generic.IEnumerable`1’ does not contain a public definition for ‘GetEnumerator’

  8. ashwin says:

    ” “

  9. Do you know if this behaviour recently changed in Visual Studio? I had previously set my linker options to include the file manually and now wanted to try out your solution using “Add Reference…”. But that dialog doesn’t seem to allow browsing the filesystem anymore.

  10. Pingback: Inter-Process communication with protocol association in WinRT – Part 3 | Anything about WinRT

  11. I do not even know how I ended up here, but I thought this post was great.
    I do not know who you are but certainly you are going to a famous blogger if you aren’t already 😉 Cheers!

  12. Howdy just wanted to give you a quick heads up.
    The words in your content seem to be running off the screen in Firefox.

    I’m not sure if this is a formatting issue or something to do with internet browser compatibility but I thought I’d post to let you know.
    The layout look great though! Hope you get the issue fixed soon.
    Many thanks

  13. Pingback: Listing Windows 8.1 Preview additions to WinRT | Anything about WinRT

  14. Pingback: DualApi Finder or listing winRT types usable by Desktop Apps | Anything about WinRT

  15. Groboto says:

    Hello, i try use this on a desktop appz, windows 8 x86
    http://code.msdn.microsoft.com/windowsapps/Edge-gesture-invocation-76a474dd

    Know some way to access to edge gestures from desktop appz and not stroe appz?

    I work i c#

    Really apreciated any info

  16. Groboto says:

    OK i have to write myself some way to catch the gestures, the problema is need disable the gestures first for not create intereference, and the oly solutio i see is this but is in c++ and i not have idea how convert to C# lol
    http://stackoverflow.com/questions/13471561/disable-windows-8-edge-gestures-hot-corners-for-multi-touch-applications-while-r/20044614#20044614

    http://msdn.microsoft.com/en-us/library/windows/desktop/jj553591(v=vs.85).aspx

    Thankyou for your repply and if you know something about C++ and can help to me, I really apreciate.

  17. I fear that you’ll have to write some native C++ code such as what is shown in http://stackoverflow.com/questions/19889683/how-do-i-turn-off-windows-8-1-gestures-and-setting-charm-bar-on-my-touch-screen where the Shell is accessed in native and call it via P/Invoke from C#

  18. Grobot says:

    I trying your code and have tis error
    System.DllNotFoundException was unhandled
    _HResult=-2146233052
    _message=Unable to load DLL ‘libDisableTouchDll.dll’: The specified module could not be found.

    Where is libDisableTouchDll.dll ? I have windows 8.1 desktop x86

  19. Grobot says:

    Please can share the dll, I not have idea how compile the dll

    Thk

  20. Grobot says:

    A guy said have error in windows 8.1 with this dll
    http://education-eco.blogspot.com.ar/2014/01/windows-81-pinvoke-dll-not-found-error.html

    Asap I have the dll I make test for see whats happen.
    Hoppe you can share the dll

    Thanks again

    • Hi Grobot,
      I’ve downloaded my source code on a x64 8.1 Update 1 machine and after recompiling in VS 2013 Update 2, everything runs fine. Since there is no P/Invoke in this simple code, there should not be any issue in loading this dll. Could you please check that you downloaded code from http://sdrv.ms/LGNNuI?

  21. Grobot says:

    Mr Christophe, I open the link you send http://sdrv.ms/LGNNuI? and tat open a web with some folder inside is marked ListInstalledMetroPackages. What not have relation with libDisableTouchDll.dll , what I need is libDisableTouchDll.dll and if possible the solution ready to compile, please can upload that and publish the link. I have 0 experience with c++ and I cant find the code in that URL for libDisableTouchDll.dll
    Also be great if you make a new post about this issue with all details, lot of guys are searching in the web how disable gestureedge for fullscreen desktop appz
    in standar x86 windows 8
    Thankyou

    • Hi Grobot,
      Please download the ListInstalledMetroPackages zip file to get the solution to compile and run. If it is not possible, here is the corresponding source code:

      // BCL namespaces
      using System;
      using System.Collections.Generic;
      using System.Security.Principal;

      // WinRT namespaces
      using Windows.ApplicationModel;
      using Windows.Management.Deployment;

      namespace ListInstalledMetroPackages {

      class Program
      {
      static void Main(string[] args)
      {
      PackageManager packageManager = new Windows.Management.Deployment.PackageManager();
      IEnumerable packages =
      packageManager.FindPackagesForUser(WindowsIdentity.GetCurrent().User.Value);
      foreach (Package package in packages)
      {
      Console.Write(package.Id.Name);

      try
      {
      Console.WriteLine(“\n ” + package.InstalledLocation.Path + “\n”);
      }
      catch (System.IO.FileNotFoundException)
      {
      Console.WriteLine(” has been deleted from its installation folder…\n”);
      }
      }
      }
      }

      As you can see, there is no need for libDisableTouchDll.dll…
      Are you sure that you are not using something else related to this dll?

  22. Grobot says:

    Me again we are talking of different things sorry.
    What I need do is what you explain in previous reply:

    I fear that you’ll have to write some native C++ code such as what is shown in http://stackoverflow.com/questions/19889683/how-do-i-turn-off-windows-8-1-gestures-and-setting-charm-bar-on-my-touch-screen where the Shell is accessed in native and call it via P/Invoke from C#

    So what I need is compile the dll what is coded in c++, and I not have ide ahow do http://pastebin.com/2v543ZWF

    Really sorry I think you have the dll

Leave a reply to Grobot Cancel reply