Relevant area(s)
PowerShell Module
Relevant command(s)
winget upgrade
Brief description of your issue
Hi,
Owing to CVE-2026-68821 where we need to update Winget/DesktopAppInstaller, I've been running through some upgrades in my lab environment and noticed some unusual behaviour.
First off, DesktopAppInstaller is not able to be uninstalled, from what I can see, it's by design.
When I update a device to the latest release, I can see both the old and new installed when using Get-AppXPackage, when I check which is provisioned, I can only see the latest version.
This then means, the updated version goes through completely fine, but it's not overwriting the older installed versions, leaving the vulnerability on the devices.
I've also tried to Set-NonRemovableAppsPolicy against the family, which doesnt work, and force register against the appxmanifest, which goes through, but the old version still lives on the device.
Since were utilising the likes of SCCM paired with either an application deployment (using the MSIX directly) or via a script install, Is there a suggested way to upgrade the application and force remove the older versions?
Steps to reproduce
Install Latest MSIX from GH Repo
Use - Get-AppxPackage -AllUsers | Where-Object {$_.Name -Like 'DesktopAppInstaller'}
Both old and new versions show in output
Try using the following script to install and register the software, however both versions still show when using the above query.
<#
.SYNOPSIS
Installs and registers the Windows Desktop App Installer.
.DESCRIPTION
Checks if Windows Desktop App Installer is present, compares the installed
version against the required version, If installed is not present or less
than required. The script will install all dependencies, install
Windows Desktop App Installer and then register the package.
.NOTES
Script Name: Install-WindowsDesktopAppInstaller.ps1
Author: Daniel Fletcher - 2026-08-18
Requires: Requires the following files "Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle",
"AppXManifest.xml", "Microsoft.VCLibs.140.00.UWPDesktop_14.0.33728.0_Universal_X64.appx",
"Microsoft.VCLibs.140.00_14.0.33519.0_Universal_X64.appx", "Microsoft.WindowsAppRuntime.1.8_8000.879.2017.0_Universal_X64.msix"
.HISTORY
Version 1.0 - Script inception
#>
######################
MARK: Functions
######################
Log file path and name
$logFilePath = "C:\Windows\fndr\logs"
$logFileName = "$logFilePath\Install-WindowsDesktopAppInstaller.log"
Function to write logs
function Write-Log {
# Write-Log function version: 1.2
param (
[string]$message
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logMessage = "$timestamp FNDR - $message"
Write-Output $logMessage
# Ensure log file path exists
if (-not (Test-Path $logFilePath)) {
New-Item -Path $logFilePath -ItemType Directory | Out-Null
}
# Write log message to log file
Add-Content -Path $logFileName -Value $logMessage
# Prune log entries older than 90 days once per script execution
if (-not $script:LogPrunedThisRun -and (Test-Path $logFileName)) {
$cutoff = (Get-Date).AddDays(-90)
$lines = Get-Content $logFileName | Where-Object {
try {
([datetime]($_.Substring(0,19))) -ge $cutoff
} catch {
$true
}
}
Set-Content -Path $logFileName -Value $lines
$script:LogPrunedThisRun = $true
}
}
######################
MARK: Variables
######################
MSIX Variables
$dependencyPath = "C:\AppInstaller\Dependencies"
$msixPath = "C:\AppInstaller\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle"
$appName = "Microsoft.DesktopAppInstaller"
System Variables
$newInstall = $false
######################
MARK: Pre-Check
######################
Check if dependencies and MSIX bundle exist
if (-not (Test-Path -Path $dependencyPath)){
Write-Log "Dependency path does not exist. Exiting script."
exit 1
}
if (-not (Test-Path -Path $msixPath)){
Write-Log "MSIX Bundle is missing. Exiting script."
exit 1
}
Write-Log "Checking if $appName is installed"
$isInstalled = Get-AppxPackage -AllUsers | Where-Object {$_.Name -like "$appName"} | Sort-Object Version -Descending | Select-Object -First 1
if($isInstalled)
{
Write-Log "$appName is installed."
Write-Log "Current Installed Version: $($isInstalled.Version)"
}
Check if Desktop App is at the required version.
$requiredVersion = "1.30.100.0"
if ($isInstalled -and [version]$isInstalled.Version -eq [version]$requiredVersion) {
Write-Log "$appName is already at the required version. No action needed."
Exit 0
}
######################
MARK: Installation
######################
Install Dependencies
foreach($dependency in Get-ChildItem $dependencyPath){
Write-Log "attempting to install dependency: $($dependency.FullName)"
try{
Add-AppxPackage -Path $dependency.FullName -ErrorAction Stop
Write-Log "Dependency: $($dependency.FullName) installed"
}catch{
Write-Log "Failed to install dependency: $($dependency.FullName). ERROR: $_"
}
}
Start-Sleep 10
Write-Log "attempting to install $appName"
try{
Add-AppxPackage -Path $msixPath -AllUsers -ErrorAction Stop
Write-Log "$appName installed successfully"
$newInstall = $true
}catch{
Write-Log "Failed to install $appName. ERROR: $_"
}
Start-Sleep 10
######################
#MARK: Registration
######################
Attempting to register package
if ($newInstall -eq $true){
$manifest = Get-AppxPackage -AllUsers | Where-Object {$.Name -like "$appName"} | Sort-Object Version -Descending | Select-Object -First 1
$regParams =@{
Register ="$($manifest.InstallLocation)\AppXManifest.xml"
DisableDevelopmentMode = $true
ForceApplicationShutdown = $true
ForceUpdateFromAnyVersion = $true
ErrorAction = 'Stop'
}
Write-Log "Attempting to register $appName..."
try {
Add-AppxPackage @regParams
Write-Log "$appName registered successfully"
}catch{
Write-Log "Failed to register $appName. ERROR: $"
}
}else{
Write-Log "Failed to install $appName, skipping registration"
exit 1
}
Expected behavior
Only latest version to show after an upgrade from the MSIX
Actual behavior
Both old and new versions show after installation of the MSIX
Environment
<#
.SYNOPSIS
Installs and registers the Windows Desktop App Installer.
.DESCRIPTION
Checks if Windows Desktop App Installer is present, compares the installed
version against the required version, If installed is not present or less
than required. The script will install all dependencies, install
Windows Desktop App Installer and then register the package.
.NOTES
Script Name: Install-WindowsDesktopAppInstaller.ps1
Author: Daniel Fletcher - 2026-08-18
Requires: Requires the following files "Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle",
"AppXManifest.xml", "Microsoft.VCLibs.140.00.UWPDesktop_14.0.33728.0_Universal_X64.appx",
"Microsoft.VCLibs.140.00_14.0.33519.0_Universal_X64.appx", "Microsoft.WindowsAppRuntime.1.8_8000.879.2017.0_Universal_X64.msix"
.HISTORY
Version 1.0 - Script inception
#>
######################
# MARK: Functions
######################
# Log file path and name
$logFilePath = "C:\Windows\fndr\logs"
$logFileName = "$logFilePath\Install-WindowsDesktopAppInstaller.log"
# Function to write logs
function Write-Log {
# Write-Log function version: 1.2
param (
[string]$message
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logMessage = "$timestamp FNDR - $message"
Write-Output $logMessage
# Ensure log file path exists
if (-not (Test-Path $logFilePath)) {
New-Item -Path $logFilePath -ItemType Directory | Out-Null
}
# Write log message to log file
Add-Content -Path $logFileName -Value $logMessage
# Prune log entries older than 90 days once per script execution
if (-not $script:LogPrunedThisRun -and (Test-Path $logFileName)) {
$cutoff = (Get-Date).AddDays(-90)
$lines = Get-Content $logFileName | Where-Object {
try {
([datetime]($_.Substring(0,19))) -ge $cutoff
} catch {
$true
}
}
Set-Content -Path $logFileName -Value $lines
$script:LogPrunedThisRun = $true
}
}
######################
# MARK: Variables
######################
# MSIX Variables
$dependencyPath = "C:\AppInstaller\Dependencies\"
$msixPath = "C:\AppInstaller\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle"
$appName = "Microsoft.DesktopAppInstaller"
# System Variables
$newInstall = $false
######################
# MARK: Pre-Check
######################
# Check if dependencies and MSIX bundle exist
if (-not (Test-Path -Path $dependencyPath)){
Write-Log "Dependency path does not exist. Exiting script."
exit 1
}
if (-not (Test-Path -Path $msixPath)){
Write-Log "MSIX Bundle is missing. Exiting script."
exit 1
}
Write-Log "Checking if $appName is installed"
$isInstalled = Get-AppxPackage -AllUsers | Where-Object {$_.Name -like "*$appName*"} | Sort-Object Version -Descending | Select-Object -First 1
if($isInstalled)
{
Write-Log "$appName is installed."
Write-Log "Current Installed Version: $($isInstalled.Version)"
}
# Check if Desktop App is at the required version.
$requiredVersion = "1.30.100.0"
if ($isInstalled -and [version]$isInstalled.Version -eq [version]$requiredVersion) {
Write-Log "$appName is already at the required version. No action needed."
Exit 0
}
######################
# MARK: Installation
######################
# Install Dependencies
foreach($dependency in Get-ChildItem $dependencyPath){
Write-Log "attempting to install dependency: $($dependency.FullName)"
try{
Add-AppxPackage -Path $dependency.FullName -ErrorAction Stop
Write-Log "Dependency: $($dependency.FullName) installed"
}catch{
Write-Log "Failed to install dependency: $($dependency.FullName). ERROR: $_"
}
}
Start-Sleep 10
Write-Log "attempting to install $appName"
try{
Add-AppxPackage -Path $msixPath -AllUsers -ErrorAction Stop
Write-Log "$appName installed successfully"
$newInstall = $true
}catch{
Write-Log "Failed to install $appName. ERROR: $_"
}
Start-Sleep 10
######################
#MARK: Registration
######################
# Attempting to register package
if ($newInstall -eq $true){
$manifest = Get-AppxPackage -AllUsers | Where-Object {$_.Name -like "*$appName*"} | Sort-Object Version -Descending | Select-Object -First 1
$regParams =@{
Register ="$($manifest.InstallLocation)\AppXManifest.xml"
DisableDevelopmentMode = $true
ForceApplicationShutdown = $true
ForceUpdateFromAnyVersion = $true
ErrorAction = 'Stop'
}
Write-Log "Attempting to register $appName..."
try {
Add-AppxPackage @regParams
Write-Log "$appName registered successfully"
}catch{
Write-Log "Failed to register $appName. ERROR: $_"
}
}else{
Write-Log "Failed to install $appName, skipping registration"
exit 1
}
Relevant area(s)
PowerShell Module
Relevant command(s)
winget upgrade
Brief description of your issue
Hi,
Owing to CVE-2026-68821 where we need to update Winget/DesktopAppInstaller, I've been running through some upgrades in my lab environment and noticed some unusual behaviour.
First off, DesktopAppInstaller is not able to be uninstalled, from what I can see, it's by design.
When I update a device to the latest release, I can see both the old and new installed when using Get-AppXPackage, when I check which is provisioned, I can only see the latest version.
This then means, the updated version goes through completely fine, but it's not overwriting the older installed versions, leaving the vulnerability on the devices.
I've also tried to Set-NonRemovableAppsPolicy against the family, which doesnt work, and force register against the appxmanifest, which goes through, but the old version still lives on the device.
Since were utilising the likes of SCCM paired with either an application deployment (using the MSIX directly) or via a script install, Is there a suggested way to upgrade the application and force remove the older versions?
Steps to reproduce
Install Latest MSIX from GH Repo
Use - Get-AppxPackage -AllUsers | Where-Object {$_.Name -Like 'DesktopAppInstaller'}
Both old and new versions show in output
Try using the following script to install and register the software, however both versions still show when using the above query.
<#
.SYNOPSIS
Installs and registers the Windows Desktop App Installer.
.DESCRIPTION
Checks if Windows Desktop App Installer is present, compares the installed
version against the required version, If installed is not present or less
than required. The script will install all dependencies, install
Windows Desktop App Installer and then register the package.
.NOTES
Script Name: Install-WindowsDesktopAppInstaller.ps1
Author: Daniel Fletcher - 2026-08-18
Requires: Requires the following files "Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle",
"AppXManifest.xml", "Microsoft.VCLibs.140.00.UWPDesktop_14.0.33728.0_Universal_X64.appx",
"Microsoft.VCLibs.140.00_14.0.33519.0_Universal_X64.appx", "Microsoft.WindowsAppRuntime.1.8_8000.879.2017.0_Universal_X64.msix"
.HISTORY
Version 1.0 - Script inception
#>
######################
MARK: Functions
######################
Log file path and name
$logFilePath = "C:\Windows\fndr\logs"
$logFileName = "$logFilePath\Install-WindowsDesktopAppInstaller.log"
Function to write logs
function Write-Log {
# Write-Log function version: 1.2
param (
[string]$message
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $logMessage = "$timestamp FNDR - $message" Write-Output $logMessage # Ensure log file path exists if (-not (Test-Path $logFilePath)) { New-Item -Path $logFilePath -ItemType Directory | Out-Null } # Write log message to log file Add-Content -Path $logFileName -Value $logMessage # Prune log entries older than 90 days once per script execution if (-not $script:LogPrunedThisRun -and (Test-Path $logFileName)) { $cutoff = (Get-Date).AddDays(-90) $lines = Get-Content $logFileName | Where-Object { try { ([datetime]($_.Substring(0,19))) -ge $cutoff } catch { $true } } Set-Content -Path $logFileName -Value $lines $script:LogPrunedThisRun = $true }}
######################
MARK: Variables
######################
MSIX Variables
$dependencyPath = "C:\AppInstaller\Dependencies"
$msixPath = "C:\AppInstaller\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle"
$appName = "Microsoft.DesktopAppInstaller"
System Variables
$newInstall = $false
######################
MARK: Pre-Check
######################
Check if dependencies and MSIX bundle exist
if (-not (Test-Path -Path $dependencyPath)){
Write-Log "Dependency path does not exist. Exiting script."
exit 1
}
if (-not (Test-Path -Path $msixPath)){
Write-Log "MSIX Bundle is missing. Exiting script."
exit 1
}
Write-Log "Checking if $appName is installed"
$isInstalled = Get-AppxPackage -AllUsers | Where-Object {$_.Name -like "$appName"} | Sort-Object Version -Descending | Select-Object -First 1
if($isInstalled)
{
Write-Log "$appName is installed."
Write-Log "Current Installed Version: $($isInstalled.Version)"
}
Check if Desktop App is at the required version.
$requiredVersion = "1.30.100.0"
if ($isInstalled -and [version]$isInstalled.Version -eq [version]$requiredVersion) {
Write-Log "$appName is already at the required version. No action needed."
Exit 0
}
######################
MARK: Installation
######################
Install Dependencies
foreach($dependency in Get-ChildItem $dependencyPath){
Write-Log "attempting to install dependency: $($dependency.FullName)"
try{
Add-AppxPackage -Path $dependency.FullName -ErrorAction Stop
Write-Log "Dependency: $($dependency.FullName) installed"
}catch{
Write-Log "Failed to install dependency: $($dependency.FullName). ERROR: $_"
}
}
Start-Sleep 10
Write-Log "attempting to install $appName"
try{
Add-AppxPackage -Path $msixPath -AllUsers -ErrorAction Stop
Write-Log "$appName installed successfully"
$newInstall = $true
}catch{
Write-Log "Failed to install $appName. ERROR: $_"
}
Start-Sleep 10
######################
#MARK: Registration
######################
Attempting to register package
if ($newInstall -eq $true){
$manifest = Get-AppxPackage -AllUsers | Where-Object {$.Name -like "$appName"} | Sort-Object Version -Descending | Select-Object -First 1
$regParams =@{
Register ="$($manifest.InstallLocation)\AppXManifest.xml"
DisableDevelopmentMode = $true
ForceApplicationShutdown = $true
ForceUpdateFromAnyVersion = $true
ErrorAction = 'Stop'
}
Write-Log "Attempting to register $appName..."
try {
Add-AppxPackage @regParams
Write-Log "$appName registered successfully"
}catch{
Write-Log "Failed to register $appName. ERROR: $"
}
}else{
Write-Log "Failed to install $appName, skipping registration"
exit 1
}
Expected behavior
Only latest version to show after an upgrade from the MSIX
Actual behavior
Both old and new versions show after installation of the MSIX
Environment