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:
- 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 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
- 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
Pingback: Windows 8 Developer Links – 2012-06-13 | Dan Rigby
Pingback: How to call WinRT APIs from C# Desktop applications – list the installed Metro packages
Pingback: Investigating BCL differences between .NET and Metro/WinRT | Anything about WinRT
This is cool. Have you found a way to initiate share operations from a desktop application?
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.
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.
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…
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’
Did you download the source code and it does not compile with VS2012?
Because it should :^)
It did notr compile till i added the following reference..
” “
Sorry abt the multiple posts .. was trying o paste this..
Reference Include=”System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”
This is weird because it is building fine as it is for me in Visual Studio 2012…
I’m glad you were able to fix it :^)
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.
Another update: after trying to resurrect a C++ console app project that uses WinRT PackageManager and was working fine on previous Win8 versions, I just found that it now throws AccessDeniedExceptions when trying to use StorageFile like it would in a Store app that lacks permissions.
Unfortunately, I did not try for a C++ project…
Pingback: Inter-Process communication with protocol association in WinRT – Part 3 | Anything about WinRT
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!
Thanks :^)
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
Thanks for the notification!
I’m not testing with Firefox currently and I’m not using any fancy layout :^(
I’ll try to figure this out
Pingback: Listing Windows 8.1 Preview additions to WinRT | Anything about WinRT
Pingback: DualApi Finder or listing winRT types usable by Desktop Apps | Anything about WinRT
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
As the MSDN documentation states (http://msdn.microsoft.com/library/en-us/windows/apps/hh701600), the EdgeGesture is only usable from a Windows Store App. Unfortunately, I don’t know any other way to get the same notification from a desktop app…
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.
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#
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
Please can share the dll, I not have idea how compile the dll
Thk
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?
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?
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
Sorry about the delay and the misunderstanding: I don’t have the .dll…
If you need to generate a .dll based on C++ code, use the walkthrough provided by MSDN such as http://msdn.microsoft.com/en-us/library/bb384842.aspx
I hope this helps