Querying Windows 8 Application Manifests for NFC launching
Recently I embarked on a supposedly simple challenge to determine if I could use Near Field Communications (NFC) to launch applications on a Windows 8 machine so I don’t have to attach a keyboard… if you ever come to the Microsoft Redmond Executive Briefing Center (EBC), I will be happy to show you, but suffice it to say that we have large numbers of touch screen PCs that do not have keyboards.
I though this would be pretty simple given that NCF communications are supported in Windows 8 as long as you have the appropriate NFC reader of course… well here goes and keep with me if you are interested in the application manifest script.
Firstly, I purchased the Sony RC S380 NFC USB reader / writer.
Next, I very carefully looked at the compatible NFC tag compatibility list (this is extremely important if you want to avoid disappointment):
・FeliCa Standard
・FeliCa Lite
・NFC Dynamic Tag (FeliCa Plug)
・Mobile FeliCa IC mobile phone
・Pico Pass
・MIFARE Classic
・MIFARE Ultralight / Ultralight C
・MIFARE DESFire / DESFire EV1
・MIFARE Plus
・Topaz/JEWEL
・ISO/IEC 14443 Type A / Type B
・ISO/IEC 14443-4 Type A / Type B (T=CL)
・NFC Forum Tag 1, 2, 3, 4A, 4B
The thing to keep in mind is that not all NFC tags are created (or indeed formatted) equal. I purchased MIFARE Classic NTAG203 tags (not the 1K version) and they worked perfectly.
Lastly, I downloaded the Windows 8 app called NFC Kits application. Note that at least one reviewer said that this application did not with the Sony RC S380 reader.. This not the case, but most likely that they didn’t have compatible tags.
When you create an Application Launch Tag, the main thing you will need to know is the App ID. This proved to be the most tricky part of the process and hence the post. The issue here is that the Application ID is constructed in the following way:
<package family name>!<app id>
Now, if you are anything like me, you start asking yourself where do I get that information from… and this is the fun part and not obvious, so I turned to my old favorite, PowerShell to help (I found very little online).
There are two main PowerShell cmdlets you need to know:
This gets a list of the app packages (.appx) that are installed in a user profile.
This gets the manifest of an app package (.appx), which is an xml file that is stored in the app directory (AppxManifest.xml). It is important because this is where the <app id> is stored, oh and where you can also find the application’s real name (more on this is a moment).
In PowerShell (important… running as administrator), if you simply execute Get-AppxPackage, it will return a list of all of the applications installed in your user profile. If you want to output this to a text file (not required, but useful) you can use:
get-appxpackage >> c:\apps.txt
This will output a list of all of the installed Windows 8 (Modern) applications to the c:\apps.txt file. For example, the Bing News application will appear as:
Name : Microsoft.BingNews
Publisher : CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
Architecture : X64
ResourceId :
Version : 2.0.0.273
PackageFullName : Microsoft.BingNews_2.0.0.273_x64__8wekyb3d8bbwe
InstallLocation : C:\Program Files\WindowsApps\Microsoft.BingNews_2.0.0.273_x64__8wekyb3d8bbwe
IsFramework : False
PackageFamilyName : Microsoft.BingNews_8wekyb3d8bbwe
PublisherId : 8wekyb3d8bbwe
You will have already noticed that part of the information you need is contained within: PackageFamilyName : Microsoft.BingNews_8wekyb3d8bbwe
The other part you need is the app id, for which you will need to use Get-AppxPackageManifest. In this instance, we want to query the manifest to find the application ID for Microsoft.BingNews_8wekyb3d8bbwe. This is achieved through the following commands:
$xml = Get-AppxPackage | Where-Object {$_.Name –like “*Microsoft.BingNews*” } | Get-AppxPackageManifest
$appID = $xml.Package.Applications.Application.Id
write-host "AppID: $appID"
The first line will query the package list for an application called *Microsoft.BingNews* and return the appropriate Manifest xml data. Note that I used wildcards here in case there are leading or following characters. I queried the $_.Name field, but could have easily used the $_.PackageFamilyName or other as required.
The second line simply parses the xml data and returns the Application ID. In this case returning:
AppID: AppexNews
One thing I did find really confusing is that the Name (in this case Microsoft.BingNews) does not necessarily align with the name of the application. Many of the 3rd party applications I came across simply used the appID of “App” which made me wonder if I could also retrieve the real name of the application. This data is also held in the xml and can be retrieved through the following:
$xml = Get-AppxPackage | Where-Object {$_.Name –like “*Microsoft.BingNews*” } | Get-AppxPackageManifest
$appID = $xml.Package.Applications.Application.Id
write-host "AppID: $appID"
$appName = $xml.Package.Properties.Displayname
write-host "AppName: $appName"
This returns:
AppID: AppexNews
AppName: ms-resource:News
This is not critical to this process, but was important when looking at some of the applications on my machine to understand exactly what they were…
Now we have enough information to construct our Application ID ( <package family name>!<app id>) , which in this case is:
PackageFamilyName : Microsoft.BingNews_8wekyb3d8bbwe!AppexNews
Putting this all together, I wanted to build a script to list all of the applications installed under my profile and build the relevant Application IDs to allow me to write NFC tags for some of them. Below is the raw script with no error handling (so beware – it is not pretty and is provided as-is with no warranty etc).
#function to return required package details
function PackageDetails
{
#define the parameter being passed to the function - in this case the PackageFullName (to avoid potential versioning issues)
Param($pname)
[hashtable]$appdetails = @{}
#retrieve xml data about the requested package
$xml = Get-AppxPackage | Where-Object {$_.PackageFullName -eq $pname } | Get-AppxPackageManifest
#retrieve appID and Displayname from XML
$appdetails.appID = $xml.Package.Applications.Application.Id
$appdetails.Appname = $xml.Package.Properties.Displayname
#return array of details
Return $appdetails
}
#main code starts here
$index=1
#Retrieve entire list of applications
$applist=Get-AppxPackage
Write-Host "Ref`t Application name, NFC AppID"
#step through the list of installed applications and retrieve their details from the manifest xml
foreach ($app in $applist)
{
$appdetails = PackageDetails $($app.PackageFullName)
Write-Host " $index`t $($app.name), $($appdetails.Appname), NFCApp=$($app.PackageFamilyName)!$($Appdetails.appID)"
$index++
}
Enjoy and let me know if you can improve on this in any way