Identify package name of an appx file

1

Is there an easier way than unzipping the appx file and inspecting files for the given scenario to obtain the full package name of an appx file?

I install a specific appx file on a machine with

Add-AppxPackage c:\my_data\Microsoft.NET.CoreRuntime.2.2.appx -ForceUpdateFromAnyVersion

On second run I get the expected error (copied from MSDN, because mine is localized)

ERROR_PACKAGE_ALREADY_EXISTS
    0x80073CFB  The provided package is already installed, and reinstallation of the package is blocked.
You may get this error if installing a package that is not bitwise identical to the package that is already installed. Note that the digital signature is also part of the package. Hence if a package is rebuilt or resigned, it is no longer bitwise identical to the previously installed package. Two possible options to fix this error are: (1) Increment the version number of the app, then rebuild and resign the package (2) Remove the old package for every user on the system before installing the new package. 

Fine. How the heck should I uninstall this app then? Usually we executed this code:

$coreFileName = "Microsoft.NET.CoreRuntime.2.2"
Get-AppxPackage | Where { $_.PackageFullName.Contains($coreFileName) } | Remove-AppxPackage

but I would remove more packages than I install because there are two identical packages and their difference is only their platform:

Name                   : Microsoft.NET.CoreRuntime.2.2
Publisher              : CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
Architecture           : X86
ResourceId             :
Version                : 2.2.27902.3
PackageFullName        : Microsoft.NET.CoreRuntime.2.2_2.2.27902.3_x86__8wekyb3d8bbwe
InstallLocation        : C:\Program Files\WindowsApps\Microsoft.NET.CoreRuntime.2.2_2.2.27902.3_x86__8wekyb3d8bbwe
IsFramework            : True
PackageFamilyName      : Microsoft.NET.CoreRuntime.2.2_8wekyb3d8bbwe
PublisherId            : 8wekyb3d8bbwe
PackageUserInformation : {S-1-5-21-73586283-1958367476-839522115-408575 [DELEC01\schulz_j]: Installed}
...

Name                   : Microsoft.NET.CoreRuntime.2.2
Publisher              : CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
Architecture           : X64
ResourceId             :
Version                : 2.2.27902.3
PackageFullName        : Microsoft.NET.CoreRuntime.2.2_2.2.27902.3_x64__8wekyb3d8bbwe
InstallLocation        : C:\Program Files\WindowsApps\Microsoft.NET.CoreRuntime.2.2_2.2.27902.3_x64__8wekyb3d8bbwe
IsFramework            : True
PackageFamilyName      : Microsoft.NET.CoreRuntime.2.2_8wekyb3d8bbwe
PublisherId            : 8wekyb3d8bbwe
PackageUserInformation : {S-1-5-21-73586283-1958367476-839522115-408575 [DELEC01\schulz_j]: Installed}
...

How should I get the real package full name, that does directly match only the package without knowing in advance what package name their will be?

I hoped for Get-AppxPackageManifest but it let me down on

Get-AppxPackageManifest c:\my_data\Microsoft.NET.CoreRuntime.2.2.appx

as it was empty.


Edit: Since I was in a haste, I did not explain the intention very well. Let me be more precise

The potentional appx file I want to install is called Microsoft.NET.CoreRuntime.2.2.appx. From the name I cannot deduct whether it is x86 or x64. When I install a newer version of this one appx file, I need to remove this and only this package.

Therefore I am looking for a way to correlate Get-AppXPackage results to the appx file.

The code

$coreFileName = "Microsoft.NET.CoreRuntime.2.2"
Get-AppxPackage | Where { $_.PackageFullName.Contains($coreFileName) }

returns two packages, x64 and x86, however since I only install one appx file, I do not want to uninstall two packages.

This is the point where I am stuck. Given the file (not the package name) above: c:\my_data\Microsoft.NET.CoreRuntime.2.2.appx, how can I get the appx details of this file?

One way would be extracting the appx file as it is only a zip and inspect the AppManifest.xml file and look for name + platform and correlate this.

But since unzipping, reading xml, deleting the zip etc is quite complex, I was looking for an easier way to do this.

windows-10
powershell
uwp
asked on Super User May 25, 2020 by Samuel • edited May 26, 2020 by Samuel

2 Answers

2

PowerShell: Get CPU bitness from within an appx file

Below is some PowerShell inspired from the IDERA Extract Specific Files from ZIP Archive post and logic. You only need to set the the full path location to the appx bundled file.

Essentially this...

  • Searches and extracts all the AppxManifest.xml file from within the specified appx file
  • Searches the extracted AppxManifest.xml file's XML content
    • From the XML 1Identity element it gets the 2ProcessArchitecture attribute value for 'CPU architecture' and saves the value to a variable (i.e. $bitness)
  • The final step removes all files within the xml-extraction-created temp folder and then removes the folder

PowerShell

$Path = "C:\Test\UWPTest\AppPackages\UWPTest_1.0.0.0_Debug_Test\Dependencies\x64\Microsoft.NET.CoreRuntime.2.2.appx";
$Filter = "AppxManifest.xml";
$OutPath = "$((Get-Childitem -Path $Path -Directory).Directory.FullName)\ztmp";

Add-Type -AssemblyName System.IO.Compression.FileSystem;

If(!(Test-Path -Path $OutPath)){New-Item -Path $OutPath -ItemType Directory -Force};

([System.IO.Compression.ZipFile]::OpenRead($Path)).Entries | % { Process {
    If($_.FullName -like $Filter){$_ | % {
        [System.IO.Compression.ZipFileExtensions]::ExtractToFile($_, "$OutPath\$($_.Name)", $true)}
        }
    }};
[System.IO.Compression.ZipFile]::OpenRead($Path).Dispose;

[xml]$xml = Get-Content "$OutPath\AppxManifest.xml";
$bitness = ((Select-Xml -Xml $Xml -XPath "*/*").Node).ProcessorArchitecture;
$bitness;

Remove-Item -Path "$OutPath" -Force -Recurse;

XML Content Example

enter image description here

<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
   xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
   xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
   IgnorableNamespaces="uap"> 
<Identity Name="Microsoft.NET.CoreRuntime.2.2" 
  ProcessorArchitecture="x64" 
  Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" 
  Version="2.2.27902.3" />
<mp:PhoneIdentity PhoneProductId="7D3B4B8B-CA47-4518-823A-A7793F27DA93" 
  PhonePublisherId="6B151E87-785E-4C4A-AA41-823B05AA9A66" />
<Properties>
  <Framework>true</Framework>
  <DisplayName>Microsoft.NET.CoreRuntime.2.2</DisplayName>
  <PublisherDisplayName>Microsoft Corporation</PublisherDisplayName>
  <Description>Microsoft .Net Core Runtime Package for Universal Windows Applications</Description>
  <Logo>logo.png</Logo>
</Properties>
<Resources>
  <Resource Language="en-US" />
</Resources>
<Dependencies>
  <TargetDeviceFamily
       Name="Windows.Universal"
       MinVersion="10.0.10049.0"
       MaxVersionTested="10.0.10049.0" />
</Dependencies> 
</Package>

Supporting Resources

answered on Super User May 29, 2020 by Pillsbury IT Doughboy • edited Jun 19, 2020 by Pillsbury IT Doughboy
1

PowerShell: Remove only appx package(s) matching a CPU bitness

Use PowerShell to set a keyword 'package name value' as an array data type variable. Loop over but use the * asterisk wildcard character before and after the iterated placeholder value "*$_*" . Expand to the PackageFullName property and save that to a new variable using the += assignment operators.

Using this method, you get an array of all the matching values from the keyword value you put in the top $Apps = @("Value") at the top so for example you are left with both full package names as below.

Microsoft.NET.CoreRuntime.2.2_2.2.27902.3_x86__8wekyb3d8bbwe
Microsoft.NET.CoreRuntime.2.2_2.2.27902.3_x64__8wekyb3d8bbwe

These values can then be piped over to | Remove-AppxPackage; to perform the removal as desired using conditional logic for example only the full package name(s) which match _x64_.

Microsoft.NET.CoreRuntime.2.2_2.2.27902.3_x64__8wekyb3d8bbwe

Powershell

$Bitness = "x64"; ## -- Set value here for what you want to remove
$Apps = @("Microsoft.NET.Native.Framework.2.2");

$base = @();
$Apps | %{
    $base += $base = (Get-AppxPackage -Name "*$_*").PackageFullName;
    };

$base;
$base | % { If($_ -match "_$($Bitness)_"){ $_ | Remove-AppxPackage } };

Supporting Resources

answered on Super User May 26, 2020 by Pillsbury IT Doughboy • edited Jun 12, 2020 by Community

User contributions licensed under CC BY-SA 3.0