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.
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 specifiedappx
file- Searches the extracted
AppxManifest.xml
file's XML content
- From the XML 1
Identity
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
$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 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>
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
$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 } };
Standard Aliases for Foreach-Object: the '
%
' symbol, ForEach
+=
: Increases the value of a variable by the specified value, or appends the specified value to the existing value.
User contributions licensed under CC BY-SA 3.0