Skip to content

Update Fleet-maintained apps - #47061

Merged
allenhouchins merged 1 commit into
mainfrom
fma-2606080400
Jun 8, 2026
Merged

Update Fleet-maintained apps#47061
allenhouchins merged 1 commit into
mainfrom
fma-2606080400

Conversation

@fleet-release

@fleet-release fleet-release commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Automated ingestion of latest Fleet-maintained app data.

Summary by CodeRabbit

  • Bug Fixes
    • Improved uninstall handling for Windows applications. Uninstall operations that require a system reboot are now correctly treated as successful completions instead of failures. This fix applies to numerous enterprise applications, ensuring more reliable software management and lifecycle operations across your fleet.

Generated automatically with cmd/maintained-apps.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Script Diff Results

ee/maintained-apps/outputs/7-zip/windows.json

=== Install Script (no changes) ===
=== Uninstall // a94a6acc -> cd80dc1f ===

--- /tmp/old.zMlVmO	2026-06-08 04:05:13.970481744 +0000
+++ /tmp/new.1P4LrW	2026-06-08 04:05:13.970481744 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{23170F69-40C1-2702-0000-000004000000}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/8x8-work/windows.json

=== Install Script (no changes) ===
=== Uninstall // 45e7dae5 -> 3f17b97d ===

--- /tmp/old.tHCpuw	2026-06-08 04:05:14.018482756 +0000
+++ /tmp/new.cj53X4	2026-06-08 04:05:14.018482756 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{66F8B350-94E0-43AF-9D26-C2385B310C96}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/aircall/windows.json

=== Install Script (no changes) ===
=== Uninstall // 22b14e09 -> fdd6312e ===

--- /tmp/old.bzUs7T	2026-06-08 04:05:14.073483916 +0000
+++ /tmp/new.xstc8s	2026-06-08 04:05:14.073483916 +0000
@@ -12,8 +12,12 @@
     Exit 1603  # ERROR_UNINSTALL_FAILURE
 }
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 # Check exit code and output result
-if ($process.ExitCode -eq 0) {
+if ($successCodes -contains $process.ExitCode) {
     Write-Output "Exit 0"
     Exit 0
 } else {

ee/maintained-apps/outputs/amazon-corretto-21/windows.json

=== Install Script (no changes) ===
=== Uninstall // 66b02de4 -> 291bae71 ===

--- /tmp/old.30f1Su	2026-06-08 04:05:14.120484907 +0000
+++ /tmp/new.oazKgu	2026-06-08 04:05:14.120484907 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{590058C2-642A-4980-A36B-A1212D1C4E5D}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/amazon-corretto-24/windows.json

=== Install Script (no changes) ===
=== Uninstall // 7963606b -> 3f9b11ee ===

--- /tmp/old.a0agFz	2026-06-08 04:05:14.168485919 +0000
+++ /tmp/new.8ii3Hh	2026-06-08 04:05:14.168485919 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{3EEF11EA-DDFA-4BF4-A5ED-DDCA47D0628C}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/amazon-corretto-25/windows.json

=== Install Script (no changes) ===
=== Uninstall // 3e2d8ea6 -> 59d14df9 ===

--- /tmp/old.hFEX2t	2026-06-08 04:05:14.218486973 +0000
+++ /tmp/new.xYZw30	2026-06-08 04:05:14.219486994 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{7C22096B-89EE-4D2E-9AAC-E7876F3409E0}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/amazon-corretto-26/windows.json

=== Install Script (no changes) ===
=== Uninstall // a6930387 -> f237f56e ===

--- /tmp/old.BCInLR	2026-06-08 04:05:14.266487985 +0000
+++ /tmp/new.5M5g0b	2026-06-08 04:05:14.266487985 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{40108932-3B67-4510-A55E-4B43E52A5FFE}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/amazon-dcv-client/windows.json

=== Install Script (no changes) ===
=== Uninstall // 0c03ed59 -> ff538764 ===

--- /tmp/old.QEy3KE	2026-06-08 04:05:14.320489124 +0000
+++ /tmp/new.y0YIkv	2026-06-08 04:05:14.320489124 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{E05BD6DA-1AA2-4A97-9326-79127EAC2A2F}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/amazon-dcv-server/windows.json

=== Install Script (no changes) ===
=== Uninstall // 45408bd1 -> e1f43f45 ===

--- /tmp/old.HQ382r	2026-06-08 04:05:14.371490199 +0000
+++ /tmp/new.XfMzw7	2026-06-08 04:05:14.371490199 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{ADED040E-8811-43F7-9A5F-E9339BC79454}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/amazon-workspaces/windows.json

=== Install Script (no changes) ===
=== Uninstall // b645e295 -> 24059738 ===

--- /tmp/old.S37PYn	2026-06-08 04:05:14.424491317 +0000
+++ /tmp/new.CR9dsR	2026-06-08 04:05:14.424491317 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{CB7B8EA8-3D5A-4233-A9CB-31A692E24E62}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/arduino-ide/windows.json

=== Install Script (no changes) ===
=== Uninstall // 7ec616d9 -> 8390d636 ===

--- /tmp/old.Vxd3aZ	2026-06-08 04:05:14.472492329 +0000
+++ /tmp/new.OZ50j2	2026-06-08 04:05:14.472492329 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{315F6168-1C48-5F6A-953D-BD5ADC41FE08}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/aws-cli/windows.json

=== Install Script (no changes) ===
=== Uninstall // 08be0723 -> 58bcd016 ===

--- /tmp/old.PuHoaN	2026-06-08 04:05:14.517493278 +0000
+++ /tmp/new.eTzptA	2026-06-08 04:05:14.517493278 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{E1C1971C-384E-4D6D-8D02-F1AC48281CF8}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/aws-vpn-client/windows.json

=== Install Script (no changes) ===
=== Uninstall // 4a75ca68 -> ff441c4a ===

--- /tmp/old.kP1NpQ	2026-06-08 04:05:14.566494311 +0000
+++ /tmp/new.dnJA3M	2026-06-08 04:05:14.566494311 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{8D1975AA-4987-4668-ACD2-66EC556E5608}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/azul-zulu-25-jdk/windows.json

=== Install Script (no changes) ===
=== Uninstall // d3f5a82d -> a2dce35a ===

--- /tmp/old.A1nWNN	2026-06-08 04:05:14.616495365 +0000
+++ /tmp/new.K2ZQGs	2026-06-08 04:05:14.616495365 +0000
@@ -12,8 +12,12 @@
     Exit 1603  # ERROR_UNINSTALL_FAILURE
 }
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 # Check exit code and output result
-if ($process.ExitCode -eq 0) {
+if ($successCodes -contains $process.ExitCode) {
     Write-Output "Exit 0"
     Exit 0
 } else {

ee/maintained-apps/outputs/azul-zulu-25-jre/windows.json

=== Install Script (no changes) ===
=== Uninstall // 890e1f0c -> ef6bb3e7 ===

--- /tmp/old.FWCfAM	2026-06-08 04:05:14.665496398 +0000
+++ /tmp/new.A4h200	2026-06-08 04:05:14.665496398 +0000
@@ -12,8 +12,12 @@
     Exit 1603  # ERROR_UNINSTALL_FAILURE
 }
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 # Check exit code and output result
-if ($process.ExitCode -eq 0) {
+if ($successCodes -contains $process.ExitCode) {
     Write-Output "Exit 0"
     Exit 0
 } else {

ee/maintained-apps/outputs/blender/windows.json

=== Install Script (no changes) ===
=== Uninstall // 65e27c01 -> 9ffd9c0e ===

--- /tmp/old.5MDK8G	2026-06-08 04:05:14.717497495 +0000
+++ /tmp/new.6qPU99	2026-06-08 04:05:14.717497495 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{4C6AD1CE-C11B-54CD-83AE-A801252310E4}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/box-drive/windows.json

=== Install Script (no changes) ===
=== Uninstall // 464f6989 -> 13b5870c ===

--- /tmp/old.Q8HgUx	2026-06-08 04:05:14.769498591 +0000
+++ /tmp/new.07DHqb	2026-06-08 04:05:14.770498612 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{46AF5B38-D258-487A-92BD-792911248CCD}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/bruno/windows.json

=== Install Script (no changes) ===
=== Uninstall // 91cf47f2 -> bfadc5e4 ===

--- /tmp/old.RVOHeS	2026-06-08 04:05:14.819499645 +0000
+++ /tmp/new.fjwsQJ	2026-06-08 04:05:14.820499667 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{41B6BEB9-60D6-5400-90FC-A4FE1C44F678}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/calibre/windows.json

=== Install Script (no changes) ===
=== Uninstall // 3169d6c2 -> 3ae8dcd8 ===

--- /tmp/old.9MZrtJ	2026-06-08 04:05:14.882500974 +0000
+++ /tmp/new.Z45YUJ	2026-06-08 04:05:14.882500974 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{5DD881FF-756B-4097-9D82-8C0F11D521EA}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/camtasia/windows.json

=== Install Script (no changes) ===
=== Uninstall // 424a13a0 -> 1c05707a ===

--- /tmp/old.tJ4abp	2026-06-08 04:05:14.935502091 +0000
+++ /tmp/new.m9LMSB	2026-06-08 04:05:14.935502091 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{CD4AC9D7-E484-41BE-AAFA-6DE4745AE6A1}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/chrome-remote-desktop/windows.json

=== Install Script (no changes) ===
=== Uninstall // 44518c74 -> 6c652c0d ===

--- /tmp/old.FYwgui	2026-06-08 04:05:14.982503082 +0000
+++ /tmp/new.8Je7eV	2026-06-08 04:05:14.982503082 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{2B21F767-E157-4FA6-963C-55834C1433A6}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/cisco-jabber/windows.json

=== Install Script (no changes) ===
=== Uninstall // 48ce752e -> 45ec9a61 ===

--- /tmp/old.fGcfc6	2026-06-08 04:05:15.029504073 +0000
+++ /tmp/new.hbW3Hq	2026-06-08 04:05:15.029504073 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{6FA51B39-4177-411C-A3A3-5A81C464278B}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/clickup/windows.json

=== Install Script (no changes) ===
=== Uninstall // e107a4f2 -> 38f3af4a ===

--- /tmp/old.jlYBBA	2026-06-08 04:05:15.082505191 +0000
+++ /tmp/new.onyr9w	2026-06-08 04:05:15.082505191 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{95C04A28-5736-505A-91E3-9132CDC33800}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/crashplan/windows.json

=== Install Script (no changes) ===
=== Uninstall // 6f26f814 -> 5eb7a6db ===

--- /tmp/old.4OB5FG	2026-06-08 04:05:15.135506308 +0000
+++ /tmp/new.FYk9D3	2026-06-08 04:05:15.136506330 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{113B48D9-4965-4FAA-A583-A61ADAE58355}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/cryptomator/windows.json

=== Install Script (no changes) ===
=== Uninstall // 86999c6b -> 1eb26343 ===

--- /tmp/old.F4z4sz	2026-06-08 04:05:15.185507363 +0000
+++ /tmp/new.u7nXpU	2026-06-08 04:05:15.185507363 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{BDA45523-42B1-4CAE-9354-A45475ED4775}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/cyberduck/windows.json

=== Install Script (no changes) ===
=== Uninstall // 691b8ed4 -> 3b278238 ===

--- /tmp/old.AmHZPz	2026-06-08 04:05:15.238508480 +0000
+++ /tmp/new.1UkKr4	2026-06-08 04:05:15.238508480 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{B9C33495-4B77-4863-9A40-4E767388647E}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/db-browser-for-sqlite/windows.json

=== Install Script (no changes) ===
=== Uninstall // a4b05830 -> 1be880ad ===

--- /tmp/old.yew2Qz	2026-06-08 04:05:15.287509513 +0000
+++ /tmp/new.ZLmpb4	2026-06-08 04:05:15.287509513 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{124623D9-35D6-4D2E-9474-2ADACC8BABBB}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/dropbox/windows.json

=== Install Script (no changes) ===
=== Uninstall // 9bebe5c6 -> 3ca1e2ae ===

--- /tmp/old.Q8l6wF	2026-06-08 04:05:15.337510568 +0000
+++ /tmp/new.37pAfy	2026-06-08 04:05:15.337510568 +0000
@@ -12,8 +12,12 @@
     Exit 1603  # ERROR_UNINSTALL_FAILURE
 }
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 # Check exit code and output result
-if ($process.ExitCode -eq 0) {
+if ($successCodes -contains $process.ExitCode) {
     Write-Output "Exit 0"
     Exit 0
 } else {

ee/maintained-apps/outputs/druva-insync/windows.json

=== Install Script (no changes) ===
=== Uninstall // b98f2558 -> 3c11d43f ===

--- /tmp/old.oXYIhA	2026-06-08 04:05:15.390511685 +0000
+++ /tmp/new.1vkFRB	2026-06-08 04:05:15.390511685 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{99ADCB07-6ABD-4A1D-AFF6-03649753BAFF}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/duo-desktop/windows.json

=== Install Script (no changes) ===
=== Uninstall // 9c181068 -> 0d338e9c ===

--- /tmp/old.59hZGE	2026-06-08 04:05:15.437512676 +0000
+++ /tmp/new.c8TwUn	2026-06-08 04:05:15.437512676 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{2C72DB34-23A1-4768-9BCB-23A6E036AA72}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/elgato-control-center/windows.json

=== Install Script (no changes) ===
=== Uninstall // cadbd5d8 -> 86c1798d ===

--- /tmp/old.IhzdJC	2026-06-08 04:05:15.483513646 +0000
+++ /tmp/new.CIs0PW	2026-06-08 04:05:15.483513646 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{1D4525F4-38FD-4D2C-9620-4283D4B8DDC3}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/elgato-stream-deck/windows.json

=== Install Script (no changes) ===
=== Uninstall // 207a4bf5 -> c3847e5b ===

--- /tmp/old.fZ4wAE	2026-06-08 04:05:15.528514595 +0000
+++ /tmp/new.7Embkh	2026-06-08 04:05:15.528514595 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{01432FFB-C9DB-40F6-8E32-575FB514874C}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/genesys-cloud/windows.json

=== Install Script (no changes) ===
=== Uninstall // 0e834aea -> 3d56a699 ===

--- /tmp/old.3uxzsy	2026-06-08 04:05:15.576515607 +0000
+++ /tmp/new.sBnhL2	2026-06-08 04:05:15.576515607 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{A0E8C487-C337-441C-83AF-90364DA4B793}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/github-desktop/windows.json

=== Install Script (no changes) ===
=== Uninstall // f0fcaa82 -> cfc2b24c ===

--- /tmp/old.kPZ5RC	2026-06-08 04:05:15.624516619 +0000
+++ /tmp/new.zt5jh2	2026-06-08 04:05:15.624516619 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{00D8E2EE-13EA-5BEB-87F0-70EFC46A7D4A}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/google-chrome/windows.json

=== Install Script (no changes) ===
=== Uninstall // 59f91bac -> 06362a80 ===

--- /tmp/old.skHBXr	2026-06-08 04:05:15.671517610 +0000
+++ /tmp/new.cA8BDZ	2026-06-08 04:05:15.671517610 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{C1DFDF69-5945-32F2-A35E-EE94C99C7CF4}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/inkscape/windows.json

=== Install Script (no changes) ===
=== Uninstall // a55ab56d -> 65f84935 ===

--- /tmp/old.n0kCdE	2026-06-08 04:05:15.724518728 +0000
+++ /tmp/new.2X1kwH	2026-06-08 04:05:15.724518728 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{4D5FEDAA-84A0-48BE-BD2A-08246398361A}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/keepassxc/windows.json

=== Install Script (no changes) ===
=== Uninstall // c4832864 -> c2cebdfd ===

--- /tmp/old.v6ZYnZ	2026-06-08 04:05:15.778519866 +0000
+++ /tmp/new.iy3v3c	2026-06-08 04:05:15.778519866 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{88785A72-3EAE-4F29-89E3-BC6B19BA9A5B}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/lastpass/windows.json

=== Install Script (no changes) ===
=== Uninstall // 42ad8ad2 -> 62d1f9f2 ===

--- /tmp/old.JJYzME	2026-06-08 04:05:15.827520900 +0000
+++ /tmp/new.C3CFqr	2026-06-08 04:05:15.828520920 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{5CD146E8-4D50-4247-AA0E-5DBFE0B2660C}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/libreoffice/windows.json

=== Install Script (no changes) ===
=== Uninstall // d8c73908 -> 731830d4 ===

--- /tmp/old.c5ZGE7	2026-06-08 04:05:15.873521870 +0000
+++ /tmp/new.p8Bwo1	2026-06-08 04:05:15.873521870 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{4B17E523-5D91-4E69-BD96-7FD81CFA81BB}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/mattermost/windows.json

=== Install Script (no changes) ===
=== Uninstall // 3e27a190 -> 1e287bf6 ===

--- /tmp/old.QCvHuR	2026-06-08 04:05:15.923522924 +0000
+++ /tmp/new.2nlUgE	2026-06-08 04:05:15.923522924 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{8523DAF0-699D-4CC7-9A65-C5E696A9DE6D}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/microsoft-edge/windows.json

=== Install Script (no changes) ===
=== Uninstall // a173cfc1 -> e12e9902 ===

--- /tmp/old.2MKhyO	2026-06-08 04:05:15.974523999 +0000
+++ /tmp/new.4ed1Ak	2026-06-08 04:05:15.974523999 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{883C2625-37F7-357F-A0F4-DFAF391B2B9C}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/mongodb-compass/windows.json

=== Install Script (no changes) ===
=== Uninstall // 450a8a79 -> 2781c2bb ===

--- /tmp/old.BeNr9v	2026-06-08 04:05:16.026525096 +0000
+++ /tmp/new.P8A1Ty	2026-06-08 04:05:16.026525096 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{0152273D-2F9F-4913-B67F-0FCD3557FFD1}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/mysqlworkbench/windows.json

=== Install Script (no changes) ===
=== Uninstall // 63a9e90e -> b99a00a6 ===

--- /tmp/old.gvAz5H	2026-06-08 04:05:16.078526192 +0000
+++ /tmp/new.aClq7I	2026-06-08 04:05:16.078526192 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{84C668F4-A0C9-4585-A463-AADE0EFC9391}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/nessus-agent/windows.json

=== Install Script (no changes) ===
=== Uninstall // fbf153ea -> 8ceaf69e ===

--- /tmp/old.FvjWIo	2026-06-08 04:05:16.125527183 +0000
+++ /tmp/new.zIRtQ0	2026-06-08 04:05:16.125527183 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{87CA4190-75C0-4DCC-84DD-DB195F745868}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/nextcloud/windows.json

=== Install Script (no changes) ===
=== Uninstall // b596a6a9 -> 625d37ef ===

--- /tmp/old.GRs8RX	2026-06-08 04:05:16.170528132 +0000
+++ /tmp/new.VUhp6N	2026-06-08 04:05:16.170528132 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{FD2FCCA9-BB8F-4485-8F70-A0621B84A7F4}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/nodejs/windows.json

=== Install Script (no changes) ===
=== Uninstall // 8f7354d9 -> aca83d80 ===

--- /tmp/old.ySdfq7	2026-06-08 04:05:16.217529123 +0000
+++ /tmp/new.UetNLz	2026-06-08 04:05:16.217529123 +0000
@@ -12,8 +12,12 @@
     Exit 1603  # ERROR_UNINSTALL_FAILURE
 }
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 # Check exit code and output result
-if ($process.ExitCode -eq 0) {
+if ($successCodes -contains $process.ExitCode) {
     Write-Output "Exit 0"
     Exit 0
 } else {

ee/maintained-apps/outputs/openvpn-connect/windows.json

=== Install Script (no changes) ===
=== Uninstall // 02b505a9 -> 9f994a0b ===

--- /tmp/old.h1ekXz	2026-06-08 04:05:16.268530198 +0000
+++ /tmp/new.BMBYrT	2026-06-08 04:05:16.268530198 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{7A36BDBE-2D2D-4771-A8F9-0F28AF7F8A2D}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/p4v/windows.json

=== Install Script (no changes) ===
=== Uninstall // 480c1bf0 -> 030745cd ===

--- /tmp/old.SQ7kWN	2026-06-08 04:05:16.337531653 +0000
+++ /tmp/new.TWLQ6W	2026-06-08 04:05:16.337531653 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{70A9FDC7-885B-4D6D-BAFD-CB2D27AB2963}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/powershell/windows.json

=== Install Script (no changes) ===
=== Uninstall // dccec067 -> 29d5a830 ===

--- /tmp/old.3NipvJ	2026-06-08 04:05:16.385532665 +0000
+++ /tmp/new.WbXd1R	2026-06-08 04:05:16.385532665 +0000
@@ -12,8 +12,12 @@
     Exit 1603  # ERROR_UNINSTALL_FAILURE
 }
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 # Check exit code and output result
-if ($process.ExitCode -eq 0) {
+if ($successCodes -contains $process.ExitCode) {
     Write-Output "Exit 0"
     Exit 0
 } else {

ee/maintained-apps/outputs/prisma-browser/windows.json

=== Install Script (no changes) ===
=== Uninstall // 28ec3eda -> 84194ed8 ===

--- /tmp/old.2UemcG	2026-06-08 04:05:16.434533698 +0000
+++ /tmp/new.KDorv2	2026-06-08 04:05:16.434533698 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{98EFE332-3AF4-336A-B6DC-D6BF52CC4C13}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/putty/windows.json

=== Install Script (no changes) ===
=== Uninstall // 4968aa57 -> 48f48e23 ===

--- /tmp/old.PBlN1p	2026-06-08 04:05:16.487534816 +0000
+++ /tmp/new.Agi7mc	2026-06-08 04:05:16.487534816 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{C9EAA861-2B72-4FAF-9FEE-EEB1AD5FD15E}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/rancher/windows.json

=== Install Script (no changes) ===
=== Uninstall // b21038db -> da741b06 ===

--- /tmp/old.3tjEkv	2026-06-08 04:05:16.539535912 +0000
+++ /tmp/new.GJBb51	2026-06-08 04:05:16.539535912 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{1F717D5A-A55B-5FE2-9103-C0D74F7FBDE3}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/snagit/windows.json

=== Install Script (no changes) ===
=== Uninstall // 6de12ca9 -> f47949a4 ===

--- /tmp/old.g9Gman	2026-06-08 04:05:16.586536903 +0000
+++ /tmp/new.9SxMzO	2026-06-08 04:05:16.586536903 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{3C12DDAF-5C49-495C-BDD9-5298E10BF718}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/sourcetree/windows.json

=== Install Script (no changes) ===
=== Uninstall // 7389fcbc -> 6b8b2b2a ===

--- /tmp/old.EPdjW0	2026-06-08 04:05:16.633537894 +0000
+++ /tmp/new.vcQKDE	2026-06-08 04:05:16.633537894 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{E18DCCFE-AFC4-42A5-A020-1FF11BF12D39}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/tailscale/windows.json

=== Install Script (no changes) ===
=== Uninstall // c9d1de3f -> b665a7bd ===

--- /tmp/old.wiadHe	2026-06-08 04:05:16.683538949 +0000
+++ /tmp/new.DYYmoo	2026-06-08 04:05:16.683538949 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{C8F0A9CE-39DE-47FE-93B4-F33AC23790B5}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/tortoisegit/windows.json

=== Install Script (no changes) ===
=== Uninstall // aaf189e3 -> f8cb22ce ===

--- /tmp/old.HH4SUB	2026-06-08 04:05:16.735540045 +0000
+++ /tmp/new.q1cqLH	2026-06-08 04:05:16.736540066 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{F46D0E11-F71A-48A0-8A7B-FD8669B5080C}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/tower/windows.json

=== Install Script (no changes) ===
=== Uninstall // b860e6c9 -> 8940833c ===

--- /tmp/old.QneWsi	2026-06-08 04:05:16.786541120 +0000
+++ /tmp/new.cDYrbl	2026-06-08 04:05:16.786541120 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{3B1FBA9F-260D-5585-9DF1-C642CA263F35}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/twingate/windows.json

=== Install Script (no changes) ===
=== Uninstall // 72d99820 -> 880ef5c9 ===

--- /tmp/old.zlcF7U	2026-06-08 04:05:16.840542259 +0000
+++ /tmp/new.8KkvDg	2026-06-08 04:05:16.840542259 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{11BA3B45-D8FA-4524-A085-80FB0A7CFC8C}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/webex/windows.json

=== Install Script (no changes) ===
=== Uninstall // dfe62b07 -> 9832a568 ===

--- /tmp/old.KrydKG	2026-06-08 04:05:16.892543356 +0000
+++ /tmp/new.nzl82P	2026-06-08 04:05:16.892543356 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{B9DCA8E9-B3A9-419A-9D6F-9BC3557EE72C}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/wireshark/windows.json

=== Install Script (no changes) ===
=== Uninstall // e23b6565 -> dc2e795d ===

--- /tmp/old.R4DRRU	2026-06-08 04:05:16.948544536 +0000
+++ /tmp/new.GsJZ4p	2026-06-08 04:05:16.948544536 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{0D67AACE-269A-4264-81A3-DA8055C1C79C}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/wrike/windows.json

=== Install Script (no changes) ===
=== Uninstall // 82aef185 -> 7675fa72 ===

--- /tmp/old.jzPH7b	2026-06-08 04:05:16.993545485 +0000
+++ /tmp/new.xkpXPS	2026-06-08 04:05:16.993545485 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{FD36F414-EF8A-48CB-8D20-BD321B03D375}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/yubico-authenticator/windows.json

=== Install Script (no changes) ===
=== Uninstall // 9bf6fdc4 -> da50bb65 ===

--- /tmp/old.fVOGAj	2026-06-08 04:05:17.048546645 +0000
+++ /tmp/new.BONavw	2026-06-08 04:05:17.048546645 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{FCBAFC57-AAAA-47B8-B861-20BDA48CD4F6}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

ee/maintained-apps/outputs/zoom/windows.json

=== Install Script (no changes) ===
=== Uninstall // b8cc88e2 -> 2e978ed3 ===

--- /tmp/old.tvahK5	2026-06-08 04:05:17.103547805 +0000
+++ /tmp/new.6HjmtB	2026-06-08 04:05:17.103547805 +0000
@@ -2,19 +2,23 @@
 $inst = New-Object -ComObject "WindowsInstaller.Installer"
 $timeoutSeconds = 300  # 5 minute timeout per product
 
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
 foreach ($product_code in $inst.RelatedProducts('{C819B794-A45C-4F27-9860-0C86492A52CC}')) {
     $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-    
+
     # Wait for process with timeout
     $completed = $process.WaitForExit($timeoutSeconds * 1000)
-    
+
     if (-not $completed) {
         Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
         Exit 1603  # ERROR_UNINSTALL_FAILURE
     }
-    
+
     # If the uninstall failed, bail
-    if ($process.ExitCode -ne 0) {
+    if ($successCodes -notcontains $process.ExitCode) {
         Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
         Exit $process.ExitCode
     }

@allenhouchins
allenhouchins merged commit 3ba71c8 into main Jun 8, 2026
11 of 13 checks passed
@allenhouchins
allenhouchins deleted the fma-2606080400 branch June 8, 2026 04:13
@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 81018a2e-9b0a-478e-bb62-6956e284c461

📥 Commits

Reviewing files that changed from the base of the PR and between 1d4650d and b1814a8.

📒 Files selected for processing (63)
  • ee/maintained-apps/outputs/7-zip/windows.json
  • ee/maintained-apps/outputs/8x8-work/windows.json
  • ee/maintained-apps/outputs/aircall/windows.json
  • ee/maintained-apps/outputs/amazon-corretto-21/windows.json
  • ee/maintained-apps/outputs/amazon-corretto-24/windows.json
  • ee/maintained-apps/outputs/amazon-corretto-25/windows.json
  • ee/maintained-apps/outputs/amazon-corretto-26/windows.json
  • ee/maintained-apps/outputs/amazon-dcv-client/windows.json
  • ee/maintained-apps/outputs/amazon-dcv-server/windows.json
  • ee/maintained-apps/outputs/amazon-workspaces/windows.json
  • ee/maintained-apps/outputs/arduino-ide/windows.json
  • ee/maintained-apps/outputs/aws-cli/windows.json
  • ee/maintained-apps/outputs/aws-vpn-client/windows.json
  • ee/maintained-apps/outputs/azul-zulu-25-jdk/windows.json
  • ee/maintained-apps/outputs/azul-zulu-25-jre/windows.json
  • ee/maintained-apps/outputs/blender/windows.json
  • ee/maintained-apps/outputs/box-drive/windows.json
  • ee/maintained-apps/outputs/bruno/windows.json
  • ee/maintained-apps/outputs/calibre/windows.json
  • ee/maintained-apps/outputs/camtasia/windows.json
  • ee/maintained-apps/outputs/chrome-remote-desktop/windows.json
  • ee/maintained-apps/outputs/cisco-jabber/windows.json
  • ee/maintained-apps/outputs/clickup/windows.json
  • ee/maintained-apps/outputs/crashplan/windows.json
  • ee/maintained-apps/outputs/cryptomator/windows.json
  • ee/maintained-apps/outputs/cyberduck/windows.json
  • ee/maintained-apps/outputs/db-browser-for-sqlite/windows.json
  • ee/maintained-apps/outputs/dropbox/windows.json
  • ee/maintained-apps/outputs/druva-insync/windows.json
  • ee/maintained-apps/outputs/duo-desktop/windows.json
  • ee/maintained-apps/outputs/elgato-control-center/windows.json
  • ee/maintained-apps/outputs/elgato-stream-deck/windows.json
  • ee/maintained-apps/outputs/genesys-cloud/windows.json
  • ee/maintained-apps/outputs/github-desktop/windows.json
  • ee/maintained-apps/outputs/google-chrome/windows.json
  • ee/maintained-apps/outputs/inkscape/windows.json
  • ee/maintained-apps/outputs/keepassxc/windows.json
  • ee/maintained-apps/outputs/lastpass/windows.json
  • ee/maintained-apps/outputs/libreoffice/windows.json
  • ee/maintained-apps/outputs/mattermost/windows.json
  • ee/maintained-apps/outputs/microsoft-edge/windows.json
  • ee/maintained-apps/outputs/mongodb-compass/windows.json
  • ee/maintained-apps/outputs/mysqlworkbench/windows.json
  • ee/maintained-apps/outputs/nessus-agent/windows.json
  • ee/maintained-apps/outputs/nextcloud/windows.json
  • ee/maintained-apps/outputs/nodejs/windows.json
  • ee/maintained-apps/outputs/openvpn-connect/windows.json
  • ee/maintained-apps/outputs/p4v/windows.json
  • ee/maintained-apps/outputs/powershell/windows.json
  • ee/maintained-apps/outputs/prisma-browser/windows.json
  • ee/maintained-apps/outputs/putty/windows.json
  • ee/maintained-apps/outputs/rancher/windows.json
  • ee/maintained-apps/outputs/snagit/windows.json
  • ee/maintained-apps/outputs/sourcetree/windows.json
  • ee/maintained-apps/outputs/tailscale/windows.json
  • ee/maintained-apps/outputs/tortoisegit/windows.json
  • ee/maintained-apps/outputs/tower/windows.json
  • ee/maintained-apps/outputs/twingate/windows.json
  • ee/maintained-apps/outputs/webex/windows.json
  • ee/maintained-apps/outputs/wireshark/windows.json
  • ee/maintained-apps/outputs/wrike/windows.json
  • ee/maintained-apps/outputs/yubico-authenticator/windows.json
  • ee/maintained-apps/outputs/zoom/windows.json

Walkthrough

This PR updates 49 Windows app manifests in the maintained-apps outputs directory. Each manifest's uninstall script reference is updated to point to a new PowerShell implementation that broadens uninstall success criteria. Where previous scripts only accepted MSI exit code 0 as success, the new scripts treat exit codes 0, 3010 (reboot required), and 1641 (reboot initiated) as successful outcomes. All other control flow—timeout enforcement, process termination on hang, and early exit on non-success codes—remains intact.

Possibly related PRs

  • fleetdm/fleet#47021: Updates Fleet uninstall PowerShell logic to accept MSI success exit codes 0, 3010, and 1641 across multiple maintained apps including TextExpander.
  • fleetdm/fleet#46538: Modifies Windows uninstall behavior to treat reboot-related exit codes as successful rather than failures in maintained-app manifests.
  • fleetdm/fleet#46307: Updates Windows uninstall PowerShell scripts to treat MSI reboot-related exit codes 3010 and 1641 as successful uninstalls alongside 0.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The PR description 'Automated ingestion of latest Fleet-maintained app data' is vague and generic, using non-descriptive language that doesn't convey meaningful details about the changeset's technical nature. Provide a more specific description explaining what MSI exit code changes are being made, why they matter (reboot scenarios), and the scope of affected applications.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Update Fleet-maintained apps' clearly summarizes the main change across all 50+ app configuration files, where uninstall scripts are being updated to handle additional MSI exit codes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fma-2606080400

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants