Fix Slack MSIX uninstall matching unrelated provisioned packages - #47039
Conversation
The Slack Windows uninstall script matched provisioned packages with $_.PackageFamilyName -eq $PACKAGE_ID. Get-AppxProvisionedPackage objects don't expose a PackageFamilyName property (it's $null), and the FMA validator doesn't substitute $PACKAGE_ID (also $null), so the filter reduced to $null -eq $null and selected every provisioned package on the machine, failing on protected packages like Microsoft.DesktopAppInstaller (exit 1603). Rewrite to match Slack by literal identity across DisplayName/PackageName (provisioned) and null-guarded Name/PackageFamilyName/Publisher (installed), following the working claude_uninstall.ps1 pattern. Regenerate the output manifest ref (ae79ce28 -> 1be2e38e). MS Teams is unaffected: msteams_uninstall.ps1 already matches a literal DisplayName, not PackageFamilyName/$PACKAGE_ID.
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.
Tip: disable this comment in your organization's Code Review settings.
Script Diff Resultsee/maintained-apps/outputs/slack/windows.json=== Install Script (no changes) ===
=== Uninstall // ae79ce28 -> 1be2e38e ===
--- /tmp/old.y1bjQI 2026-06-07 17:15:49.676156020 +0000
+++ /tmp/new.LoFyWq 2026-06-07 17:15:49.676156020 +0000
@@ -1,23 +1,46 @@
-$packageFamilyName = 'com.tinyspeck.slackdesktop_8yrtsj140pw4g'
$timeoutSeconds = 300 # 5 minute timeout
+# Match only Slack (published by Slack Technologies). We deliberately do NOT rely
+# on $PACKAGE_ID or on a PackageFamilyName property: Get-AppxProvisionedPackage
+# objects don't expose PackageFamilyName, so an "-eq" match against it is $null on
+# every package and would select unrelated packages (e.g. DesktopAppInstaller).
+function ShouldRemoveSlackPackage {
+ param([Parameter(Mandatory=$true)]$pkg)
+ try {
+ $name = [string]$pkg.Name
+ $family = [string]$pkg.PackageFamilyName
+ $publisher = [string]$pkg.Publisher
+
+ if ($name -and ($name -like "*Slack*")) { return $true }
+ if ($family -and ($family -like "*Slack*")) { return $true }
+ if ($publisher -and ($publisher -like "*Slack Technologies*") -and $name -and ($name -like "*Slack*")) { return $true }
+ } catch {}
+ return $false
+}
+
try {
$start = Get-Date
- $provisioned = Get-AppxProvisionedPackage -Online -ErrorAction Stop |
- Where-Object { $_.PackageFamilyName -eq $packageFamilyName }
+
+ $provisioned = Get-AppxProvisionedPackage -Online -ErrorAction Stop | Where-Object {
+ ($_.DisplayName -and ($_.DisplayName -like "*Slack*")) -or
+ ($_.PackageName -and ($_.PackageName -like "*Slack*"))
+ }
foreach ($pkg in $provisioned) {
- Remove-AppxProvisionedPackage -Online -PackageName $pkg.PackageName -AllUsers -ErrorAction Stop
+ Write-Host "Removing provisioned package: $($pkg.PackageName)"
+ Remove-AppxProvisionedPackage -Online -PackageName $pkg.PackageName -AllUsers -ErrorAction Stop | Out-String | Write-Host
$elapsed = (New-TimeSpan -Start $start).TotalSeconds
if ($elapsed -gt $timeoutSeconds) {
Exit 1603
}
}
- $installed = Get-AppxPackage -AllUsers -PackageTypeFilter Main -ErrorAction SilentlyContinue |
- Where-Object { $_.PackageFamilyName -eq $packageFamilyName }
+ $installed = Get-AppxPackage -AllUsers -PackageTypeFilter Main -ErrorAction SilentlyContinue | Where-Object {
+ ShouldRemoveSlackPackage $_
+ }
foreach ($app in $installed) {
- Remove-AppxPackage -Package $app.PackageFullName -AllUsers -ErrorAction Stop
+ Write-Host "Removing installed package: $($app.PackageFullName)"
+ Remove-AppxPackage -Package $app.PackageFullName -AllUsers -ErrorAction Stop | Out-String | Write-Host
$elapsed = (New-TimeSpan -Start $start).TotalSeconds
if ($elapsed -gt $timeoutSeconds) {
Exit 1603 |
There was a problem hiding this comment.
Pull request overview
This PR updates the Slack (Windows MSIX/winget) uninstall logic to avoid accidentally matching and attempting to remove unrelated provisioned Appx packages, and refreshes the generated maintained-app manifest output to reference the new uninstall script.
Changes:
- Rewrites
slack_uninstall.ps1to avoid$PACKAGE_IDsubstitution and to filter provisioned/installed packages by properties available at runtime. - Updates the Slack Windows maintained-app output manifest to point at the regenerated uninstall script ref.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| ee/maintained-apps/outputs/slack/windows.json | Updates uninstall_script_ref and embedded uninstall script ref content for Slack Windows MSIX. |
| ee/maintained-apps/inputs/winget/scripts/slack_uninstall.ps1 | Replaces uninstall matching logic to avoid selecting unrelated Appx provisioned packages. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if ($name -and ($name -like "*Slack*")) { return $true } | ||
| if ($family -and ($family -like "*Slack*")) { return $true } | ||
| if ($publisher -and ($publisher -like "*Slack Technologies*") -and $name -and ($name -like "*Slack*")) { return $true } |
| $provisioned = Get-AppxProvisionedPackage -Online -ErrorAction Stop | Where-Object { | ||
| ($_.DisplayName -and ($_.DisplayName -like "*Slack*")) -or | ||
| ($_.PackageName -and ($_.PackageName -like "*Slack*")) | ||
| } |
WalkthroughThis PR updates the Windows Slack uninstall process to use flexible pattern matching instead of hardcoded package identity checks. It introduces a 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
ee/maintained-apps/inputs/winget/scripts/slack_uninstall.ps1 (1)
14-16: ⚡ Quick winRemove unreachable condition on line 16.
Line 16 can never return
truebecause:
- If
$namecontains "Slack", line 14 would have already returnedtrue- So by the time execution reaches line 16, we know
$nameis either null/empty OR does not contain "Slack"- But line 16 requires
$nameto be non-empty AND contain "Slack" – a contradictionThe current logic with lines 14-15 already correctly matches Slack packages by Name or PackageFamilyName. Line 16 adds no additional coverage.
♻️ Proposed fix to remove dead code
if ($name -and ($name -like "*Slack*")) { return $true } if ($family -and ($family -like "*Slack*")) { return $true } - if ($publisher -and ($publisher -like "*Slack Technologies*") -and $name -and ($name -like "*Slack*")) { return $true } } catch {}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@ee/maintained-apps/inputs/winget/scripts/slack_uninstall.ps1` around lines 14 - 16, The third conditional that checks "if ($publisher -and ($publisher -like "*Slack Technologies*") -and $name -and ($name -like "*Slack*")) { return $true }" is unreachable because earlier checks already return true when $name contains "Slack"; remove this redundant if entirely, or if the intent was to match by publisher even when $name is missing, replace it with a publisher-only check using $publisher -like "*Slack Technologies*" to return true.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@ee/maintained-apps/inputs/winget/scripts/slack_uninstall.ps1`:
- Around line 14-16: The third conditional that checks "if ($publisher -and
($publisher -like "*Slack Technologies*") -and $name -and ($name -like
"*Slack*")) { return $true }" is unreachable because earlier checks already
return true when $name contains "Slack"; remove this redundant if entirely, or
if the intent was to match by publisher even when $name is missing, replace it
with a publisher-only check using $publisher -like "*Slack Technologies*" to
return true.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: ecdaf112-ab14-4e40-9a61-1fd4e791c95c
📒 Files selected for processing (2)
ee/maintained-apps/inputs/winget/scripts/slack_uninstall.ps1ee/maintained-apps/outputs/slack/windows.json
Problem
The Slack Windows (winget/MSIX) uninstall script selected provisioned packages with:
Two bugs compound here:
Get-AppxProvisionedPackageobjects have noPackageFamilyNameproperty (that's onGet-AppxPackageresults), so$_.PackageFamilyNameis$nullfor every provisioned package.$PACKAGE_ID— it runs the raw ref script with no substitution — so$packageFamilyNameis also$null.The filter reduces to
$null -eq $null→ true for every package, so the script tries to remove all provisioned packages on the machine and fails on protected ones likeMicrosoft.DesktopAppInstaller(exit code 1603). This is the same failure mode just fixed for Affinity.Fix
Rewrite
slack_uninstall.ps1to match Slack by literal identity — acrossDisplayName/PackageNamefor provisioned packages and null-guardedName/PackageFamilyName/Publisherfor installed packages — following the workingclaude_uninstall.ps1pattern. No longer depends on$PACKAGE_IDsubstitution or a property the provisioned object lacks, so it works in both the validator and production.Regenerated the output manifest ref:
ae79ce28→1be2e38e(content hash verified against the source script).Note on MS Teams
msteams_uninstall.ps1is not affected — it matches a literalDisplayName("MSTeams"), a real property on provisioned packages, rather thanPackageFamilyName/$PACKAGE_ID. No change needed.Testing
Summary by CodeRabbit