Add 17 Windows Fleet-maintained apps - #48501
Conversation
Adds Windows FMAs for apps identified as deployed in the ManageEngine SDP environment but missing Fleet coverage: AOMEI Backupper Standard, Apple iTunes, Azure Data Studio, CrystalDiskMark, Dell Display and Peripheral Manager, Eclipse Temurin JDK 11, Eclipse Temurin JRE 8, Git Extensions, GNU Privacy Guard, Google Earth Pro, Gpg4win, Logitech Unifying Software, Logi Tune, Rtools, SonicWall NetExtender, Spyder, TightVNC, TreeSize Free, WinDirStat, Yarn, and Zoom Outlook Plugin. MSI-type apps use auto-generated install/uninstall scripts with upgrade-code-based uninstall. EXE-type apps include custom PS1 scripts with appropriate silent flags (Inno Setup, NSIS, WiX bundle, or vendor-specific). Eclipse Temurin JDK 11 and JRE 8 use custom exists_query with LIKE matching since the registry DisplayName includes version and architecture suffixes.
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.
There was a problem hiding this comment.
Pull request overview
Adds 21 new Windows Fleet-maintained apps (FMAs) to the maintained-apps catalog by introducing new winget input definitions (and custom PS scripts where needed), generating corresponding output manifests, and registering the apps in the aggregated apps.json list.
Changes:
- Added 21 new Windows app definitions under
ee/maintained-apps/inputs/winget/(plus install/uninstall scripts for EXE-based installers). - Added generated Windows output manifests under
ee/maintained-apps/outputs/<app>/windows.json. - Updated the maintained-apps catalog index (
outputs/apps.json) and added a user-visible change entry.
Reviewed changes
Copilot reviewed 69 out of 70 changed files in this pull request and generated 18 comments.
Show a summary per file
| File | Description |
|---|---|
| ee/maintained-apps/outputs/zoom-outlook-plugin/windows.json | New Windows output manifest (MSI) |
| ee/maintained-apps/outputs/yarn/windows.json | New Windows output manifest (MSI) |
| ee/maintained-apps/outputs/windirstat/windows.json | New Windows output manifest (MSI) |
| ee/maintained-apps/outputs/treesize-free/windows.json | New Windows output manifest (EXE + scripts) |
| ee/maintained-apps/outputs/tightvnc/windows.json | New Windows output manifest (MSI) |
| ee/maintained-apps/outputs/spyder/windows.json | New Windows output manifest (EXE + scripts) |
| ee/maintained-apps/outputs/sonicwall-netextender/windows.json | New Windows output manifest (MSI) |
| ee/maintained-apps/outputs/rtools/windows.json | New Windows output manifest (EXE + scripts) |
| ee/maintained-apps/outputs/logitune/windows.json | New Windows output manifest (EXE + scripts) |
| ee/maintained-apps/outputs/logitech-unifying-software/windows.json | New Windows output manifest (EXE + scripts) |
| ee/maintained-apps/outputs/gpg4win/windows.json | New Windows output manifest (EXE + scripts) |
| ee/maintained-apps/outputs/google-earth-pro/windows.json | New Windows output manifest (EXE + scripts) |
| ee/maintained-apps/outputs/gnupg/windows.json | New Windows output manifest (EXE + scripts) |
| ee/maintained-apps/outputs/git-extensions/windows.json | New Windows output manifest (MSI) |
| ee/maintained-apps/outputs/eclipse-temurin-jre-8/windows.json | New Windows output manifest (MSI + LIKE exists) |
| ee/maintained-apps/outputs/eclipse-temurin-jdk-11/windows.json | New Windows output manifest (MSI + LIKE exists) |
| ee/maintained-apps/outputs/dell-display-and-peripheral-manager/windows.json | New Windows output manifest (EXE + scripts) |
| ee/maintained-apps/outputs/crystaldiskmark/windows.json | New Windows output manifest (EXE + scripts) |
| ee/maintained-apps/outputs/azure-data-studio/windows.json | New Windows output manifest (EXE + scripts) |
| ee/maintained-apps/outputs/apple-itunes/windows.json | New Windows output manifest (EXE + scripts) |
| ee/maintained-apps/outputs/aomei-backupper-standard/windows.json | New Windows output manifest (EXE + scripts) |
| ee/maintained-apps/outputs/apps.json | Register new Windows apps in catalog |
| ee/maintained-apps/inputs/winget/zoom-outlook-plugin.json | New winget input definition |
| ee/maintained-apps/inputs/winget/yarn.json | New winget input definition |
| ee/maintained-apps/inputs/winget/windirstat.json | New winget input definition |
| ee/maintained-apps/inputs/winget/treesize-free.json | New winget input definition + script paths |
| ee/maintained-apps/inputs/winget/tightvnc.json | New winget input definition |
| ee/maintained-apps/inputs/winget/spyder.json | New winget input definition + script paths |
| ee/maintained-apps/inputs/winget/sonicwall-netextender.json | New winget input definition |
| ee/maintained-apps/inputs/winget/rtools.json | New winget input definition + script paths |
| ee/maintained-apps/inputs/winget/logitune.json | New winget input definition + script paths |
| ee/maintained-apps/inputs/winget/logitech-unifying-software.json | New winget input definition + script paths |
| ee/maintained-apps/inputs/winget/gpg4win.json | New winget input definition + script paths |
| ee/maintained-apps/inputs/winget/google-earth-pro.json | New winget input definition + script paths |
| ee/maintained-apps/inputs/winget/gnupg.json | New winget input definition + script paths |
| ee/maintained-apps/inputs/winget/git-extensions.json | New winget input definition |
| ee/maintained-apps/inputs/winget/eclipse-temurin-jre-8.json | New winget input definition + custom exists_query |
| ee/maintained-apps/inputs/winget/eclipse-temurin-jdk-11.json | New winget input definition + custom exists_query |
| ee/maintained-apps/inputs/winget/dell-display-and-peripheral-manager.json | New winget input definition + script paths |
| ee/maintained-apps/inputs/winget/crystaldiskmark.json | New winget input definition + script paths |
| ee/maintained-apps/inputs/winget/azure-data-studio.json | New winget input definition + script paths |
| ee/maintained-apps/inputs/winget/apple-itunes.json | New winget input definition + script paths |
| ee/maintained-apps/inputs/winget/aomei-backupper-standard.json | New winget input definition + script paths |
| ee/maintained-apps/inputs/winget/scripts/treesize_free_uninstall.ps1 | Custom uninstall script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/treesize_free_install.ps1 | Custom install script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/spyder_uninstall.ps1 | Custom uninstall script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/spyder_install.ps1 | Custom install script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/rtools_uninstall.ps1 | Custom uninstall script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/rtools_install.ps1 | Custom install script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/logitune_uninstall.ps1 | Custom uninstall script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/logitune_install.ps1 | Custom install script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/logitech_unifying_software_uninstall.ps1 | Custom uninstall script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/logitech_unifying_software_install.ps1 | Custom install script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/gpg4win_uninstall.ps1 | Custom uninstall script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/gpg4win_install.ps1 | Custom install script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/google_earth_pro_uninstall.ps1 | Custom uninstall script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/google_earth_pro_install.ps1 | Custom install script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/gnupg_uninstall.ps1 | Custom uninstall script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/gnupg_install.ps1 | Custom install script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/dell_dapm_uninstall.ps1 | Custom uninstall script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/dell_dapm_install.ps1 | Custom install script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/crystaldiskmark_uninstall.ps1 | Custom uninstall script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/crystaldiskmark_install.ps1 | Custom install script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/azure_data_studio_uninstall.ps1 | Custom uninstall script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/azure_data_studio_install.ps1 | Custom install script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/apple_itunes_uninstall.ps1 | Custom uninstall script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/apple_itunes_install.ps1 | Custom install script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/aomei_backupper_standard_uninstall.ps1 | Custom uninstall script (EXE) |
| ee/maintained-apps/inputs/winget/scripts/aomei_backupper_standard_install.ps1 | Custom install script (EXE) |
| changes/add-windows-fmas-batch | Release note entry |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Add 18 icon TSX components and website PNG assets for all new Windows FMAs (AOMEI, iTunes, Azure Data Studio, CrystalDiskMark, Dell DAPM, Eclipse Temurin JDK 11/JRE 8, Git Extensions, GnuPG, Gpg4win, Logitech Unifying, Rtools, SonicWall, TightVNC, TreeSize Free, WinDirStat, Yarn, Zoom Outlook Plugin) - Update icon index.ts with alphabetically sorted imports and map entries - Fix CrystalDiskMark unique_identifier matching to use LIKE 'CrystalDiskMark %' since Inno Setup installers register as "CrystalDiskMark 9" in registry - Fix map key for iTunes (slug-derived "apple itunes" → "itunes") - Fix map key for GnuPG (slug-derived "gnupg" → "gnu privacy guard")
WalkthroughThis PR adds 21 new Fleet-maintained Windows applications to the maintained-apps pipeline. For each app, a Winget input manifest JSON is added under Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 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.
Actionable comments posted: 8
Note
Due to the large number of review comments, Critical severity comments were prioritized as inline comments.
🟠 Major comments (13)
ee/maintained-apps/inputs/winget/eclipse-temurin-jre-8.json-6-10 (1)
6-10: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winConstrain the custom exists query to x64 installs.
Same problem here: the manifest selects the x64 MSI, but Line 6 does not filter on the architecture suffix. That lets another Temurin 8 JRE variant satisfy both existence and patch checks for this app.
Suggested fix
- "exists_query": "SELECT 1 FROM programs WHERE name LIKE 'Eclipse Temurin JRE with Hotspot 8%' AND publisher = 'Eclipse Adoptium';", + "exists_query": "SELECT 1 FROM programs WHERE name LIKE 'Eclipse Temurin JRE with Hotspot 8% (x64)' AND publisher = 'Eclipse Adoptium';",🤖 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/eclipse-temurin-jre-8.json` around lines 6 - 10, The custom exists_query in the Temurin 8 JRE winget input is too broad because it matches any Eclipse Temurin JRE with Hotspot 8 entry regardless of architecture. Tighten the query used by this manifest so it explicitly filters for x64 installs, aligning it with the selected x64 MSI and preventing other Temurin 8 JRE variants from satisfying the existence and patch checks. Update the exists_query entry in this manifest to include the architecture suffix condition alongside the existing name and publisher constraints.ee/maintained-apps/inputs/winget/eclipse-temurin-jdk-11.json-6-10 (1)
6-10: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winConstrain the custom exists query to x64 installs.
This manifest pins
installer_archtox64, but Line 6 matches every Temurin 11 JDK display name with that prefix. Because this custom query also feeds the generated patched query, an x86/ARM64 install can be treated as the x64 app being present and current.Suggested fix
- "exists_query": "SELECT 1 FROM programs WHERE name LIKE 'Eclipse Temurin JDK with Hotspot 11%' AND publisher = 'Eclipse Adoptium';", + "exists_query": "SELECT 1 FROM programs WHERE name LIKE 'Eclipse Temurin JDK with Hotspot 11% (x64)' AND publisher = 'Eclipse Adoptium';",🤖 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/eclipse-temurin-jdk-11.json` around lines 6 - 10, The custom exists_query is too broad and can match non-x64 Temurin 11 installs, causing the x64 manifest to be treated as present when it is not. Update the query in the Eclipse Temurin JDK 11 winget manifest to constrain results to x64 installs, using the existing installer_arch setting as the guide so the generated patched query only matches x64 entries.ee/maintained-apps/inputs/winget/scripts/azure_data_studio_install.ps1-16-16 (1)
16-16: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winFix the
Start-Processsplat on line 16.@$processOptionsis treated as a literal argument here, soStart-Processgets@$processOptionsinstead of the hashtable values and the installer never launches.🤖 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/azure_data_studio_install.ps1` at line 16, The Start-Process call in the Azure Data Studio install script is using an invalid splat form, so the hashtable is being passed as a literal argument instead of expanded parameters. Update the invocation at the Start-Process call site to use the proper splatting syntax with the existing processOptions hashtable so the installer launches correctly.ee/maintained-apps/outputs/rtools/windows.json-19-20 (1)
19-20: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winRegenerate this output after fixing the PowerShell splat typo in the source scripts.
ee/maintained-apps/outputs/rtools/windows.jsonstill embedsStart-Process @$processOptionsin both refs, so the committed artifact will stay broken until it is refreshed from the updated install/uninstall scripts.🤖 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/outputs/rtools/windows.json` around lines 19 - 20, The generated Rtools PowerShell outputs are still stale and contain the broken splat usage in both the uninstall and install script entries, so refresh this artifact from the updated source scripts. Regenerate the `windows.json` output for the Rtools package after fixing the `Start-Process` splat typo so the embedded scripts in both referenced entries are updated consistently.ee/maintained-apps/inputs/winget/scripts/rtools_install.ps1-16-16 (1)
16-16: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winFix the PowerShell splat syntax.
Start-Processneeds@processOptions, not@$processOptions; this causes a parameter-binding error, and the same generated line appears in the other winget installer/uninstaller scripts.Proposed fix
-$process = Start-Process @$processOptions +$process = Start-Process `@processOptions`🤖 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/rtools_install.ps1` at line 16, The Start-Process call is using invalid PowerShell splat syntax, which causes parameter binding to fail. Update the generated Start-Process invocation in rtools_install.ps1 to use the processOptions splat correctly, and apply the same fix to the matching Start-Process lines in the other winget installer/uninstaller scripts so they all use the same valid pattern.ee/maintained-apps/inputs/winget/scripts/rtools_uninstall.ps1-24-26 (1)
24-26: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winFix the
Start-Processsplat syntax — use@processOptionshere;@$processOptionswill prevent the uninstall command from starting.🤖 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/rtools_uninstall.ps1` around lines 24 - 26, The Start-Process call in rtools_uninstall.ps1 is using the wrong splat syntax, which prevents the uninstall command from launching. Update the invocation that builds $processOptions and calls Start-Process so it splats the hashtable with `@processOptions` instead of @$processOptions, keeping the existing FilePath, ArgumentList, PassThru, and Wait behavior intact.ee/maintained-apps/outputs/zoom-outlook-plugin/windows.json-21-21 (1)
21-21: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winQuote the MSI log path in the command line.
$logFileis embedded in a single-ArgumentListstring, so a space in%TEMP%will split/lvand can makemsiexecfail before install starts.🤖 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/outputs/zoom-outlook-plugin/windows.json` at line 21, The msiexec invocation in the windows.json entry builds a single -ArgumentList string in the Start-Process call, so the $logFile value from the /lv switch can break if %TEMP% contains spaces. Update the logic around the Start-Process msiexec.exe command to ensure the MSI log path is quoted/escaped as a single argument, keeping the /lv target intact while preserving the existing INSTALLER_PATH and ExitCode handling.ee/maintained-apps/inputs/winget/scripts/azure_data_studio_uninstall.ps1-24-26 (1)
24-26: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winUse
@processOptionshere.@$processOptionsis invalid splatting syntax, soStart-Processwon’t bind the options and the uninstall path fails.Proposed fix
- $process = Start-Process @$processOptions + $process = Start-Process `@processOptions`🤖 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/azure_data_studio_uninstall.ps1` around lines 24 - 26, The Start-Process call in azure_data_studio_uninstall.ps1 is using invalid splatting syntax, so the options in $processOptions will not bind correctly and the uninstall flow can fail. Update the Start-Process invocation in the uninstall script to use the proper splat form with the $processOptions hashtable, and keep the existing $uninstallCommand/$uninstallArgs handling intact.ee/maintained-apps/inputs/winget/scripts/aomei_backupper_standard_uninstall.ps1-24-26 (1)
24-26: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winFix the splatting typo in
ee/maintained-apps/inputs/winget/scripts/aomei_backupper_standard_uninstall.ps1:26.
Start-Process @$processOptionsis invalid PowerShell splatting; it needs to be@processOptions, or this uninstall path will fail.🤖 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/aomei_backupper_standard_uninstall.ps1` around lines 24 - 26, The `Start-Process` call in `aomei_backupper_standard_uninstall.ps1` is using invalid splatting syntax, so the uninstall flow will break when it runs. Update the `Start-Process` invocation to use the `processOptions` hashtable with proper PowerShell splatting in the uninstall logic, keeping the existing `uninstallCommand`, `uninstallArgs`, and `$processOptions` setup unchanged.ee/maintained-apps/inputs/winget/scripts/gnupg_uninstall.ps1-4-10 (1)
4-10: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winCover HKCU installs or force machine scope
installer_scopeis empty here and the install script doesn’t force a machine install, so a per-user GnuPG install would be detected but never uninstalled. Add the HKCU uninstall hives here, or make the package machine-scoped upstream.🤖 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/gnupg_uninstall.ps1` around lines 4 - 10, The uninstall lookup in gnupg_uninstall.ps1 only scans machine-wide registry hives, so per-user GnuPG installs can be missed. Update the registry search used by the uninstall flow (the $machineKey / $machineKey32on64 lookup in the script) to also include the equivalent HKCU uninstall hives, or otherwise ensure the package is forced to machine scope so the uninstall path covers all installed instances.ee/maintained-apps/outputs/eclipse-temurin-jdk-11/windows.json-21-21 (1)
21-21: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winNormalize MSI reboot-required exit codes in the shared install ref. This
8959087bscript returns the rawmsiexeccode, so successful installs that end with3010or1641will be treated as failures. The same ref is reused across multiple Windows manifests, so handle those codes once here.🤖 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/outputs/eclipse-temurin-jdk-11/windows.json` at line 21, The shared install script for the 8959087b reference currently exits with the raw msiexec result, so reboot-required success codes are being treated as failures. Update the script in the shared Windows install ref to normalize the Start-Process msiexec.exe exit handling: after the install finishes, treat 3010 and 1641 as successful outcomes and return a zero exit code, while preserving non-success codes as failures. Keep the change centered around the 8959087b entry so all manifests using this reference inherit the fix.ee/maintained-apps/inputs/winget/scripts/google_earth_pro_uninstall.ps1-3-3 (1)
3-3: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winAdd the MSI silent uninstall flag to the fallback path
Google Earth Prouninstalls throughmsiexec, soUninstallStringwithout/qncan still prompt UI in unattended runs. Handle the MSI case explicitly instead of relying onQuietUninstallString.🤖 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/google_earth_pro_uninstall.ps1` at line 3, The fallback uninstall path in google_earth_pro_uninstall.ps1 does not guarantee silent execution for MSI-based removals. Update the logic around the UninstallString handling to detect the Google Earth Pro msiexec case and append the MSI silent flag (/qn) explicitly instead of depending on QuietUninstallString; keep the change focused on the uninstall argument construction used by the script’s uninstall flow.ee/maintained-apps/inputs/winget/scripts/treesize_free_uninstall.ps1-24-26 (1)
24-26: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winUse
@processOptionshere instead of@$processOptions. PowerShell splatting takes the variable name directly; this typo prevents the uninstall arguments from being passed.Suggested fix
- $process = Start-Process @$processOptions + $process = Start-Process `@processOptions`🤖 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/treesize_free_uninstall.ps1` around lines 24 - 26, The uninstall flow in the script’s Start-Process call is using the wrong splatting syntax, which prevents the arguments from being passed. Update the process launch in the uninstall block to use the splatted $processOptions variable directly with the Start-Process invocation, keeping the existing $processOptions construction and $uninstallArgs handling intact.
🤖 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.
Inline comments:
In
`@ee/maintained-apps/inputs/winget/scripts/aomei_backupper_standard_install.ps1`:
- Line 16: The Start-Process invocation in the install script is using invalid
splatting syntax, so it will not parse. Update the Start-Process call in the
script to use the proper `@processOptions` splat form, keeping the existing
processOptions variable and surrounding logic unchanged.
In
`@ee/maintained-apps/inputs/winget/scripts/logitech_unifying_software_install.ps1`:
- Line 16: The Start-Process call in logitech_unifying_software_install.ps1 is
using invalid splat syntax with $processOptions, which prevents the script from
parsing. Update the Start-Process invocation to use the proper PowerShell splat
form for the existing processOptions variable so the call is valid and the
script can execute. Use the unique symbol Start-Process and the processOptions
variable to locate and correct this line.
In
`@ee/maintained-apps/inputs/winget/scripts/logitech_unifying_software_uninstall.ps1`:
- Line 26: The uninstall launcher is using invalid splatting syntax in the
Start-Process call, which prevents the uninstaller from starting. Update the
invocation in the logitech_unifying_software_uninstall.ps1 script to use valid
splatting with the existing $processOptions variable, and then regenerate the
matching windows.json output ref for the Logitech Unifying Software app so the
package metadata stays in sync.
In `@ee/maintained-apps/inputs/winget/scripts/spyder_uninstall.ps1`:
- Around line 24-26: The uninstall script is using invalid splat syntax in the
Start-Process call, which prevents the command from running. Update the
Start-Process invocation in spyder_uninstall.ps1 to use the hashtable variable
with proper PowerShell splatting, and keep the existing $processOptions
construction and optional ArgumentList assignment intact.
In `@ee/maintained-apps/outputs/aomei-backupper-standard/windows.json`:
- Around line 19-20: The embedded PowerShell payloads for the install and
uninstall refs are using invalid splat syntax in Start-Process, which will break
execution. Update both script bodies in the AOMEI Backupper Standard entries so
Start-Process splats the processOptions hashtable correctly using the existing
$processOptions symbol, and make sure the same fix is applied in both the
installer and uninstaller refs.
In `@ee/maintained-apps/outputs/azure-data-studio/windows.json`:
- Around line 19-20: The embedded PowerShell in both Azure Data Studio script
entries is using invalid splatting syntax with Start-Process, which will prevent
the installer and uninstaller from running. Update the calls in the install and
uninstall script blobs to use proper splatting against the $processOptions
hashtable in both places where Start-Process is invoked. Keep the rest of the
logic in the 1dc8cafc and 87cf9389 script entries unchanged.
In `@ee/maintained-apps/outputs/spyder/windows.json`:
- Line 19: The Spyder Windows install script payload is using invalid splatting
syntax in the Start-Process invocation. Update the source script that generates
the Spyder Windows output so the $processOptions hashtable is passed with
standard PowerShell splatting syntax in Start-Process, then regenerate the
windows.json artifact to reflect the corrected payload. Use the Start-Process
and $processOptions symbols to locate and fix the source of the generated
output.
In `@ee/maintained-apps/outputs/treesize-free/windows.json`:
- Around line 19-20: The TreeSize Free install and uninstall scripts are using
invalid PowerShell splatting with Start-Process, so update both script payloads
referenced by the install and uninstall entries to use the correct splat syntax
in the Start-Process call. Locate the Start-Process usage in the TreeSize Free
PowerShell blobs and fix the argument expansion so the process launch works
before regenerating the refs.
---
Major comments:
In `@ee/maintained-apps/inputs/winget/eclipse-temurin-jdk-11.json`:
- Around line 6-10: The custom exists_query is too broad and can match non-x64
Temurin 11 installs, causing the x64 manifest to be treated as present when it
is not. Update the query in the Eclipse Temurin JDK 11 winget manifest to
constrain results to x64 installs, using the existing installer_arch setting as
the guide so the generated patched query only matches x64 entries.
In `@ee/maintained-apps/inputs/winget/eclipse-temurin-jre-8.json`:
- Around line 6-10: The custom exists_query in the Temurin 8 JRE winget input is
too broad because it matches any Eclipse Temurin JRE with Hotspot 8 entry
regardless of architecture. Tighten the query used by this manifest so it
explicitly filters for x64 installs, aligning it with the selected x64 MSI and
preventing other Temurin 8 JRE variants from satisfying the existence and patch
checks. Update the exists_query entry in this manifest to include the
architecture suffix condition alongside the existing name and publisher
constraints.
In
`@ee/maintained-apps/inputs/winget/scripts/aomei_backupper_standard_uninstall.ps1`:
- Around line 24-26: The `Start-Process` call in
`aomei_backupper_standard_uninstall.ps1` is using invalid splatting syntax, so
the uninstall flow will break when it runs. Update the `Start-Process`
invocation to use the `processOptions` hashtable with proper PowerShell
splatting in the uninstall logic, keeping the existing `uninstallCommand`,
`uninstallArgs`, and `$processOptions` setup unchanged.
In `@ee/maintained-apps/inputs/winget/scripts/azure_data_studio_install.ps1`:
- Line 16: The Start-Process call in the Azure Data Studio install script is
using an invalid splat form, so the hashtable is being passed as a literal
argument instead of expanded parameters. Update the invocation at the
Start-Process call site to use the proper splatting syntax with the existing
processOptions hashtable so the installer launches correctly.
In `@ee/maintained-apps/inputs/winget/scripts/azure_data_studio_uninstall.ps1`:
- Around line 24-26: The Start-Process call in azure_data_studio_uninstall.ps1
is using invalid splatting syntax, so the options in $processOptions will not
bind correctly and the uninstall flow can fail. Update the Start-Process
invocation in the uninstall script to use the proper splat form with the
$processOptions hashtable, and keep the existing
$uninstallCommand/$uninstallArgs handling intact.
In `@ee/maintained-apps/inputs/winget/scripts/gnupg_uninstall.ps1`:
- Around line 4-10: The uninstall lookup in gnupg_uninstall.ps1 only scans
machine-wide registry hives, so per-user GnuPG installs can be missed. Update
the registry search used by the uninstall flow (the $machineKey /
$machineKey32on64 lookup in the script) to also include the equivalent HKCU
uninstall hives, or otherwise ensure the package is forced to machine scope so
the uninstall path covers all installed instances.
In `@ee/maintained-apps/inputs/winget/scripts/google_earth_pro_uninstall.ps1`:
- Line 3: The fallback uninstall path in google_earth_pro_uninstall.ps1 does not
guarantee silent execution for MSI-based removals. Update the logic around the
UninstallString handling to detect the Google Earth Pro msiexec case and append
the MSI silent flag (/qn) explicitly instead of depending on
QuietUninstallString; keep the change focused on the uninstall argument
construction used by the script’s uninstall flow.
In `@ee/maintained-apps/inputs/winget/scripts/rtools_install.ps1`:
- Line 16: The Start-Process call is using invalid PowerShell splat syntax,
which causes parameter binding to fail. Update the generated Start-Process
invocation in rtools_install.ps1 to use the processOptions splat correctly, and
apply the same fix to the matching Start-Process lines in the other winget
installer/uninstaller scripts so they all use the same valid pattern.
In `@ee/maintained-apps/inputs/winget/scripts/rtools_uninstall.ps1`:
- Around line 24-26: The Start-Process call in rtools_uninstall.ps1 is using the
wrong splat syntax, which prevents the uninstall command from launching. Update
the invocation that builds $processOptions and calls Start-Process so it splats
the hashtable with `@processOptions` instead of @$processOptions, keeping the
existing FilePath, ArgumentList, PassThru, and Wait behavior intact.
In `@ee/maintained-apps/inputs/winget/scripts/treesize_free_uninstall.ps1`:
- Around line 24-26: The uninstall flow in the script’s Start-Process call is
using the wrong splatting syntax, which prevents the arguments from being
passed. Update the process launch in the uninstall block to use the splatted
$processOptions variable directly with the Start-Process invocation, keeping the
existing $processOptions construction and $uninstallArgs handling intact.
In `@ee/maintained-apps/outputs/eclipse-temurin-jdk-11/windows.json`:
- Line 21: The shared install script for the 8959087b reference currently exits
with the raw msiexec result, so reboot-required success codes are being treated
as failures. Update the script in the shared Windows install ref to normalize
the Start-Process msiexec.exe exit handling: after the install finishes, treat
3010 and 1641 as successful outcomes and return a zero exit code, while
preserving non-success codes as failures. Keep the change centered around the
8959087b entry so all manifests using this reference inherit the fix.
In `@ee/maintained-apps/outputs/rtools/windows.json`:
- Around line 19-20: The generated Rtools PowerShell outputs are still stale and
contain the broken splat usage in both the uninstall and install script entries,
so refresh this artifact from the updated source scripts. Regenerate the
`windows.json` output for the Rtools package after fixing the `Start-Process`
splat typo so the embedded scripts in both referenced entries are updated
consistently.
In `@ee/maintained-apps/outputs/zoom-outlook-plugin/windows.json`:
- Line 21: The msiexec invocation in the windows.json entry builds a single
-ArgumentList string in the Start-Process call, so the $logFile value from the
/lv switch can break if %TEMP% contains spaces. Update the logic around the
Start-Process msiexec.exe command to ensure the MSI log path is quoted/escaped
as a single argument, keeping the /lv target intact while preserving the
existing INSTALLER_PATH and ExitCode handling.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 744b175c-03e4-4164-bbf5-5f3eb94012b4
📒 Files selected for processing (70)
changes/add-windows-fmas-batchee/maintained-apps/inputs/winget/aomei-backupper-standard.jsonee/maintained-apps/inputs/winget/apple-itunes.jsonee/maintained-apps/inputs/winget/azure-data-studio.jsonee/maintained-apps/inputs/winget/crystaldiskmark.jsonee/maintained-apps/inputs/winget/dell-display-and-peripheral-manager.jsonee/maintained-apps/inputs/winget/eclipse-temurin-jdk-11.jsonee/maintained-apps/inputs/winget/eclipse-temurin-jre-8.jsonee/maintained-apps/inputs/winget/git-extensions.jsonee/maintained-apps/inputs/winget/gnupg.jsonee/maintained-apps/inputs/winget/google-earth-pro.jsonee/maintained-apps/inputs/winget/gpg4win.jsonee/maintained-apps/inputs/winget/logitech-unifying-software.jsonee/maintained-apps/inputs/winget/logitune.jsonee/maintained-apps/inputs/winget/rtools.jsonee/maintained-apps/inputs/winget/scripts/aomei_backupper_standard_install.ps1ee/maintained-apps/inputs/winget/scripts/aomei_backupper_standard_uninstall.ps1ee/maintained-apps/inputs/winget/scripts/apple_itunes_install.ps1ee/maintained-apps/inputs/winget/scripts/apple_itunes_uninstall.ps1ee/maintained-apps/inputs/winget/scripts/azure_data_studio_install.ps1ee/maintained-apps/inputs/winget/scripts/azure_data_studio_uninstall.ps1ee/maintained-apps/inputs/winget/scripts/crystaldiskmark_install.ps1ee/maintained-apps/inputs/winget/scripts/crystaldiskmark_uninstall.ps1ee/maintained-apps/inputs/winget/scripts/dell_dapm_install.ps1ee/maintained-apps/inputs/winget/scripts/dell_dapm_uninstall.ps1ee/maintained-apps/inputs/winget/scripts/gnupg_install.ps1ee/maintained-apps/inputs/winget/scripts/gnupg_uninstall.ps1ee/maintained-apps/inputs/winget/scripts/google_earth_pro_install.ps1ee/maintained-apps/inputs/winget/scripts/google_earth_pro_uninstall.ps1ee/maintained-apps/inputs/winget/scripts/gpg4win_install.ps1ee/maintained-apps/inputs/winget/scripts/gpg4win_uninstall.ps1ee/maintained-apps/inputs/winget/scripts/logitech_unifying_software_install.ps1ee/maintained-apps/inputs/winget/scripts/logitech_unifying_software_uninstall.ps1ee/maintained-apps/inputs/winget/scripts/logitune_install.ps1ee/maintained-apps/inputs/winget/scripts/logitune_uninstall.ps1ee/maintained-apps/inputs/winget/scripts/rtools_install.ps1ee/maintained-apps/inputs/winget/scripts/rtools_uninstall.ps1ee/maintained-apps/inputs/winget/scripts/spyder_install.ps1ee/maintained-apps/inputs/winget/scripts/spyder_uninstall.ps1ee/maintained-apps/inputs/winget/scripts/treesize_free_install.ps1ee/maintained-apps/inputs/winget/scripts/treesize_free_uninstall.ps1ee/maintained-apps/inputs/winget/sonicwall-netextender.jsonee/maintained-apps/inputs/winget/spyder.jsonee/maintained-apps/inputs/winget/tightvnc.jsonee/maintained-apps/inputs/winget/treesize-free.jsonee/maintained-apps/inputs/winget/windirstat.jsonee/maintained-apps/inputs/winget/yarn.jsonee/maintained-apps/inputs/winget/zoom-outlook-plugin.jsonee/maintained-apps/outputs/aomei-backupper-standard/windows.jsonee/maintained-apps/outputs/apple-itunes/windows.jsonee/maintained-apps/outputs/apps.jsonee/maintained-apps/outputs/azure-data-studio/windows.jsonee/maintained-apps/outputs/crystaldiskmark/windows.jsonee/maintained-apps/outputs/dell-display-and-peripheral-manager/windows.jsonee/maintained-apps/outputs/eclipse-temurin-jdk-11/windows.jsonee/maintained-apps/outputs/eclipse-temurin-jre-8/windows.jsonee/maintained-apps/outputs/git-extensions/windows.jsonee/maintained-apps/outputs/gnupg/windows.jsonee/maintained-apps/outputs/google-earth-pro/windows.jsonee/maintained-apps/outputs/gpg4win/windows.jsonee/maintained-apps/outputs/logitech-unifying-software/windows.jsonee/maintained-apps/outputs/logitune/windows.jsonee/maintained-apps/outputs/rtools/windows.jsonee/maintained-apps/outputs/sonicwall-netextender/windows.jsonee/maintained-apps/outputs/spyder/windows.jsonee/maintained-apps/outputs/tightvnc/windows.jsonee/maintained-apps/outputs/treesize-free/windows.jsonee/maintained-apps/outputs/windirstat/windows.jsonee/maintained-apps/outputs/yarn/windows.jsonee/maintained-apps/outputs/zoom-outlook-plugin/windows.json
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #48501 +/- ##
==========================================
- Coverage 67.95% 67.95% -0.01%
==========================================
Files 3922 3935 +13
Lines 250015 250038 +23
Branches 13178 13334 +156
==========================================
+ Hits 169888 169903 +15
- Misses 64833 64842 +9
+ Partials 15294 15293 -1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
- Fix PowerShell splatting bug: `@$processOptions` → `@processOptions` in 12 install/uninstall scripts (AOMEI, Azure Data Studio, Logitech Unifying Software, Rtools, Spyder, TreeSize Free) - Fix SourceForge installer URL: append /download suffix so Go HTTP client downloads the binary instead of the HTML download page; update winget ingester to auto-apply this for any SourceForge URL without the suffix - Fix Logi Tune SHA256: add ignore_hash=true since the download URL is unversioned and winget manifest lags behind Logitech releases - Fix iTunes/Google Earth Pro uninstall: add msiexec wait loop after uninstall command, since both use wrapper EXEs that exit before child MSI processes complete - Freeze Dell DAPM: requires physical Dell display hardware not available in CI runners; mark frozen to skip CI validation - Regenerate affected output JSONs for all modified apps
Script Diff Resultsee/maintained-apps/outputs/aomei-backupper-standard/windows.json=== Install // 34b42c0a -> 03d967ed ===
--- /tmp/old.KxRDsU 2026-06-30 18:51:06.064075158 +0000
+++ /tmp/new.DwHdoU 2026-06-30 18:51:06.064075158 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 90ede407 -> 2a469c3f ===
--- /tmp/old.XXtbuU 2026-06-30 18:51:06.100075511 +0000
+++ /tmp/new.rNLUau 2026-06-30 18:51:06.100075511 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/apple-itunes/windows.json=== Install Script (no changes) ===
=== Uninstall // 5f74ea2b -> ac09716c ===
--- /tmp/old.H4PIGI 2026-06-30 18:51:06.146075962 +0000
+++ /tmp/new.3xfR9j 2026-06-30 18:51:06.147075972 +0000
@@ -30,4 +30,13 @@
if (-not $foundUninstaller) { Write-Host "Uninstaller for '$softwareName' not found."; Exit 1 }
} catch { Write-Host "Error: $_"; Exit 1 }
+# iTunes uses a WiX bundle that spawns child msiexec processes; wait for them to finish
+$timeout = 120
+$elapsed = 0
+while ((Get-Process -Name "msiexec" -ErrorAction SilentlyContinue) -and ($elapsed -lt $timeout)) {
+ Start-Sleep -Seconds 2
+ $elapsed += 2
+ Write-Host "Waiting for msiexec to complete... ($elapsed seconds)"
+}
+
Exit $exitCodeee/maintained-apps/outputs/azure-data-studio/windows.json=== Install // 1dc8cafc -> 622c4e10 ===
--- /tmp/old.0rcXU8 2026-06-30 18:51:06.277077246 +0000
+++ /tmp/new.fY2L7z 2026-06-30 18:51:06.277077246 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 87cf9389 -> 23fce27b ===
--- /tmp/old.uGgOaz 2026-06-30 18:51:06.293077403 +0000
+++ /tmp/new.Z4zOam 2026-06-30 18:51:06.293077403 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/crystaldiskmark/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/dell-display-and-peripheral-manager/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/eclipse-temurin-jdk-11/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/eclipse-temurin-jre-8/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/git-extensions/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/gnupg/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/google-earth-pro/windows.json=== Install Script (no changes) ===
=== Uninstall // 7e72e637 -> 51dc162a ===
--- /tmp/old.OBKWj6 2026-06-30 18:51:07.467087918 +0000
+++ /tmp/new.ayizCM 2026-06-30 18:51:07.467087918 +0000
@@ -65,4 +65,13 @@
Exit 1
}
+# Google Earth Pro's uninstaller spawns child msiexec processes; wait for them to finish
+$timeout = 120
+$elapsed = 0
+while ((Get-Process -Name "msiexec" -ErrorAction SilentlyContinue) -and ($elapsed -lt $timeout)) {
+ Start-Sleep -Seconds 2
+ $elapsed += 2
+ Write-Host "Waiting for msiexec to complete... ($elapsed seconds)"
+}
+
Exit $exitCodeee/maintained-apps/outputs/gpg4win/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/logitech-unifying-software/windows.json=== Install // f7bcd4ba -> a3795eea ===
--- /tmp/old.qMO0NT 2026-06-30 18:51:07.735090277 +0000
+++ /tmp/new.pbdZPY 2026-06-30 18:51:07.735090277 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 9f1b824a -> 8ec563fd ===
--- /tmp/old.RTunBt 2026-06-30 18:51:07.751090418 +0000
+++ /tmp/new.B53doI 2026-06-30 18:51:07.751090418 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/logitune/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/rtools/windows.json=== Install // adeab869 -> fec8495e ===
--- /tmp/old.mAYqXx 2026-06-30 18:51:07.829091104 +0000
+++ /tmp/new.bxGJJZ 2026-06-30 18:51:07.829091104 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 6125a07b -> a289eb1d ===
--- /tmp/old.tc3k80 2026-06-30 18:51:07.845091245 +0000
+++ /tmp/new.zkIN31 2026-06-30 18:51:07.845091245 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/sonicwall-netextender/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/spyder/windows.json=== Install // 297c1c96 -> 6831586d ===
--- /tmp/old.BSLYhF 2026-06-30 18:51:08.119093657 +0000
+++ /tmp/new.uAW7rC 2026-06-30 18:51:08.119093657 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 338688ef -> 1fe840b2 ===
--- /tmp/old.ovDZjD 2026-06-30 18:51:08.135093797 +0000
+++ /tmp/new.WVAwJA 2026-06-30 18:51:08.135093797 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/tightvnc/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/treesize-free/windows.json=== Install // 3e307826 -> 36e33a58 ===
--- /tmp/old.JBgmaw 2026-06-30 18:51:08.409096209 +0000
+++ /tmp/new.hPi2iW 2026-06-30 18:51:08.410096218 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 3cc408af -> f316b604 ===
--- /tmp/old.hHBAkG 2026-06-30 18:51:08.425096350 +0000
+++ /tmp/new.sizpHp 2026-06-30 18:51:08.425096350 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/windirstat/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/yarn/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/zoom-outlook-plugin/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) === |
CrystalDiskMark uses a SourceForge installer URL that requires a /download suffix to serve the binary directly to non-browser HTTP clients, but the winget manifest doesn't include that suffix. Rather than patching the ingester broadly, drop CrystalDiskMark from the batch. Reverts the SourceForge /download logic added to winget ingester.go. Removes input JSON, install/uninstall scripts, output JSON, icon, and apps.json entry. Updates changes file from 21 to 20 apps.
Script Diff Resultsee/maintained-apps/outputs/aomei-backupper-standard/windows.json=== Install // 34b42c0a -> 03d967ed ===
--- /tmp/old.8BnFdz 2026-06-30 19:24:27.187970929 +0000
+++ /tmp/new.EdiQFP 2026-06-30 19:24:27.187970929 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 90ede407 -> 2a469c3f ===
--- /tmp/old.7ZPcVJ 2026-06-30 19:24:27.210971162 +0000
+++ /tmp/new.U2wQmy 2026-06-30 19:24:27.210971162 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/apple-itunes/windows.json=== Install Script (no changes) ===
=== Uninstall // 5f74ea2b -> ac09716c ===
--- /tmp/old.KSYDhM 2026-06-30 19:24:27.253971599 +0000
+++ /tmp/new.25vb4i 2026-06-30 19:24:27.253971599 +0000
@@ -30,4 +30,13 @@
if (-not $foundUninstaller) { Write-Host "Uninstaller for '$softwareName' not found."; Exit 1 }
} catch { Write-Host "Error: $_"; Exit 1 }
+# iTunes uses a WiX bundle that spawns child msiexec processes; wait for them to finish
+$timeout = 120
+$elapsed = 0
+while ((Get-Process -Name "msiexec" -ErrorAction SilentlyContinue) -and ($elapsed -lt $timeout)) {
+ Start-Sleep -Seconds 2
+ $elapsed += 2
+ Write-Host "Waiting for msiexec to complete... ($elapsed seconds)"
+}
+
Exit $exitCodeee/maintained-apps/outputs/azure-data-studio/windows.json=== Install // 1dc8cafc -> 622c4e10 ===
--- /tmp/old.NWfJ4i 2026-06-30 19:24:27.379972878 +0000
+++ /tmp/new.aHNcwG 2026-06-30 19:24:27.379972878 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 87cf9389 -> 23fce27b ===
--- /tmp/old.XpSlah 2026-06-30 19:24:27.393973020 +0000
+++ /tmp/new.GZs441 2026-06-30 19:24:27.393973020 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/dell-display-and-peripheral-manager/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/eclipse-temurin-jdk-11/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/eclipse-temurin-jre-8/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/git-extensions/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/gnupg/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/google-earth-pro/windows.json=== Install Script (no changes) ===
=== Uninstall // 7e72e637 -> 51dc162a ===
--- /tmp/old.dj813W 2026-06-30 19:24:28.421983459 +0000
+++ /tmp/new.3IIlQD 2026-06-30 19:24:28.421983459 +0000
@@ -65,4 +65,13 @@
Exit 1
}
+# Google Earth Pro's uninstaller spawns child msiexec processes; wait for them to finish
+$timeout = 120
+$elapsed = 0
+while ((Get-Process -Name "msiexec" -ErrorAction SilentlyContinue) -and ($elapsed -lt $timeout)) {
+ Start-Sleep -Seconds 2
+ $elapsed += 2
+ Write-Host "Waiting for msiexec to complete... ($elapsed seconds)"
+}
+
Exit $exitCodeee/maintained-apps/outputs/gpg4win/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/logitech-unifying-software/windows.json=== Install // f7bcd4ba -> a3795eea ===
--- /tmp/old.XPfclN 2026-06-30 19:24:28.658985866 +0000
+++ /tmp/new.x9hBFE 2026-06-30 19:24:28.658985866 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 9f1b824a -> 8ec563fd ===
--- /tmp/old.P1vZ7o 2026-06-30 19:24:28.673986018 +0000
+++ /tmp/new.j8HBN7 2026-06-30 19:24:28.673986018 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/logitune/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/rtools/windows.json=== Install // adeab869 -> fec8495e ===
--- /tmp/old.xPjzee 2026-06-30 19:24:28.743986729 +0000
+++ /tmp/new.YNH88Q 2026-06-30 19:24:28.743986729 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 6125a07b -> a289eb1d ===
--- /tmp/old.oFlaeh 2026-06-30 19:24:28.758986881 +0000
+++ /tmp/new.gQmcmy 2026-06-30 19:24:28.758986881 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/sonicwall-netextender/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/spyder/windows.json=== Install // 297c1c96 -> 6831586d ===
--- /tmp/old.oT20sT 2026-06-30 19:24:29.004989379 +0000
+++ /tmp/new.7ZSttZ 2026-06-30 19:24:29.004989379 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 338688ef -> 1fe840b2 ===
--- /tmp/old.PzBPNp 2026-06-30 19:24:29.018989521 +0000
+++ /tmp/new.Sm8WKW 2026-06-30 19:24:29.018989521 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/tightvnc/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/treesize-free/windows.json=== Install // 3e307826 -> 36e33a58 ===
--- /tmp/old.dz6AQa 2026-06-30 19:24:29.264992019 +0000
+++ /tmp/new.KLmgrE 2026-06-30 19:24:29.264992019 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 3cc408af -> f316b604 ===
--- /tmp/old.STrkEg 2026-06-30 19:24:29.279992172 +0000
+++ /tmp/new.L4Thxq 2026-06-30 19:24:29.279992172 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/windirstat/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/yarn/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/zoom-outlook-plugin/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) === |
Script Diff Resultsee/maintained-apps/outputs/aomei-backupper-standard/windows.json=== Install // 34b42c0a -> 03d967ed ===
--- /tmp/old.n4Qxmx 2026-06-30 19:27:03.098666177 +0000
+++ /tmp/new.WNWJ99 2026-06-30 19:27:03.098666177 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 90ede407 -> 2a469c3f ===
--- /tmp/old.jCv0D1 2026-06-30 19:27:03.115666048 +0000
+++ /tmp/new.PwQxib 2026-06-30 19:27:03.115666048 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/apple-itunes/windows.json=== Install Script (no changes) ===
=== Uninstall // 5f74ea2b -> ac09716c ===
--- /tmp/old.g2gPIj 2026-06-30 19:27:03.161665699 +0000
+++ /tmp/new.WKTfve 2026-06-30 19:27:03.161665699 +0000
@@ -30,4 +30,13 @@
if (-not $foundUninstaller) { Write-Host "Uninstaller for '$softwareName' not found."; Exit 1 }
} catch { Write-Host "Error: $_"; Exit 1 }
+# iTunes uses a WiX bundle that spawns child msiexec processes; wait for them to finish
+$timeout = 120
+$elapsed = 0
+while ((Get-Process -Name "msiexec" -ErrorAction SilentlyContinue) -and ($elapsed -lt $timeout)) {
+ Start-Sleep -Seconds 2
+ $elapsed += 2
+ Write-Host "Waiting for msiexec to complete... ($elapsed seconds)"
+}
+
Exit $exitCodeee/maintained-apps/outputs/azure-data-studio/windows.json=== Install // 1dc8cafc -> 622c4e10 ===
--- /tmp/old.3WxfS2 2026-06-30 19:27:03.292664705 +0000
+++ /tmp/new.JaTkrH 2026-06-30 19:27:03.292664705 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 87cf9389 -> 23fce27b ===
--- /tmp/old.x4QQei 2026-06-30 19:27:03.309664576 +0000
+++ /tmp/new.MiwvqJ 2026-06-30 19:27:03.309664576 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/dell-display-and-peripheral-manager/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/eclipse-temurin-jdk-11/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/eclipse-temurin-jre-8/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/git-extensions/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/gnupg/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/google-earth-pro/windows.json=== Install Script (no changes) ===
=== Uninstall // 7e72e637 -> 51dc162a ===
--- /tmp/old.dvc2ho 2026-06-30 19:27:04.469655777 +0000
+++ /tmp/new.BFoQbg 2026-06-30 19:27:04.469655777 +0000
@@ -65,4 +65,13 @@
Exit 1
}
+# Google Earth Pro's uninstaller spawns child msiexec processes; wait for them to finish
+$timeout = 120
+$elapsed = 0
+while ((Get-Process -Name "msiexec" -ErrorAction SilentlyContinue) -and ($elapsed -lt $timeout)) {
+ Start-Sleep -Seconds 2
+ $elapsed += 2
+ Write-Host "Waiting for msiexec to complete... ($elapsed seconds)"
+}
+
Exit $exitCodeee/maintained-apps/outputs/gpg4win/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/logitech-unifying-software/windows.json=== Install // f7bcd4ba -> a3795eea ===
--- /tmp/old.SRSum1 2026-06-30 19:27:04.743653699 +0000
+++ /tmp/new.EvR2o1 2026-06-30 19:27:04.743653699 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 9f1b824a -> 8ec563fd ===
--- /tmp/old.HzScuU 2026-06-30 19:27:04.759653578 +0000
+++ /tmp/new.BkVtJo 2026-06-30 19:27:04.759653578 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/logitune/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/rtools/windows.json=== Install // adeab869 -> fec8495e ===
--- /tmp/old.8vKEwT 2026-06-30 19:27:04.836652994 +0000
+++ /tmp/new.A5bbAn 2026-06-30 19:27:04.836652994 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 6125a07b -> a289eb1d ===
--- /tmp/old.896Z4q 2026-06-30 19:27:04.853652865 +0000
+++ /tmp/new.LzajZq 2026-06-30 19:27:04.853652865 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/sonicwall-netextender/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/spyder/windows.json=== Install // 297c1c96 -> 6831586d ===
--- /tmp/old.r2oMNT 2026-06-30 19:27:05.130650764 +0000
+++ /tmp/new.WQiZ5q 2026-06-30 19:27:05.130650764 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 338688ef -> 1fe840b2 ===
--- /tmp/old.1FDOZV 2026-06-30 19:27:05.147650635 +0000
+++ /tmp/new.mwollQ 2026-06-30 19:27:05.147650635 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/tightvnc/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/treesize-free/windows.json=== Install // 3e307826 -> 36e33a58 ===
--- /tmp/old.DfdEPX 2026-06-30 19:27:05.429648495 +0000
+++ /tmp/new.rdT5X7 2026-06-30 19:27:05.429648495 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 3cc408af -> f316b604 ===
--- /tmp/old.dzSrLj 2026-06-30 19:27:05.445648374 +0000
+++ /tmp/new.Y98SL9 2026-06-30 19:27:05.445648374 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/windirstat/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/yarn/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/zoom-outlook-plugin/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) === |
CI Feedback 🧐A test triggered by this PR failed. Here is an AI-generated analysis of the failure:
|
…h-2026-06 # Conflicts: # ee/maintained-apps/inputs/winget/eclipse-temurin-jdk-11.json # ee/maintained-apps/inputs/winget/eclipse-temurin-jre-8.json # ee/maintained-apps/inputs/winget/windirstat.json # ee/maintained-apps/outputs/apps.json # ee/maintained-apps/outputs/eclipse-temurin-jdk-11/windows.json # ee/maintained-apps/outputs/eclipse-temurin-jre-8/windows.json # ee/maintained-apps/outputs/windirstat/windows.json # frontend/pages/SoftwarePage/components/icons/EclipseTemurinJdk11.tsx # frontend/pages/SoftwarePage/components/icons/EclipseTemurinJre8.tsx # frontend/pages/SoftwarePage/components/icons/Windirstat.tsx # frontend/pages/SoftwarePage/components/icons/index.ts # website/assets/images/app-icon-eclipse-temurin-jdk-11-60x60@2x.png # website/assets/images/app-icon-eclipse-temurin-jre-8-60x60@2x.png # website/assets/images/app-icon-windirstat-60x60@2x.png
Script Diff Resultsee/maintained-apps/outputs/aomei-backupper-standard/windows.json=== Install // 34b42c0a -> 03d967ed ===
--- /tmp/old.QxzqzM 2026-07-27 19:19:34.329086701 +0000
+++ /tmp/new.gEYau3 2026-07-27 19:19:34.329086701 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 90ede407 -> 2a469c3f ===
--- /tmp/old.F94a0n 2026-07-27 19:19:34.346087063 +0000
+++ /tmp/new.HaPVC4 2026-07-27 19:19:34.346087063 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/apple-itunes/windows.json=== Install Script (no changes) ===
=== Uninstall // 5f74ea2b -> ac09716c ===
--- /tmp/old.AmQX6U 2026-07-27 19:19:34.397088148 +0000
+++ /tmp/new.il5aBa 2026-07-27 19:19:34.397088148 +0000
@@ -30,4 +30,13 @@
if (-not $foundUninstaller) { Write-Host "Uninstaller for '$softwareName' not found."; Exit 1 }
} catch { Write-Host "Error: $_"; Exit 1 }
+# iTunes uses a WiX bundle that spawns child msiexec processes; wait for them to finish
+$timeout = 120
+$elapsed = 0
+while ((Get-Process -Name "msiexec" -ErrorAction SilentlyContinue) -and ($elapsed -lt $timeout)) {
+ Start-Sleep -Seconds 2
+ $elapsed += 2
+ Write-Host "Waiting for msiexec to complete... ($elapsed seconds)"
+}
+
Exit $exitCodeee/maintained-apps/outputs/azure-data-studio/windows.json=== Install // 1dc8cafc -> 622c4e10 ===
--- /tmp/old.79JtQB 2026-07-27 19:19:34.535091084 +0000
+++ /tmp/new.elkOKM 2026-07-27 19:19:34.535091084 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 87cf9389 -> 23fce27b ===
--- /tmp/old.GFSErd 2026-07-27 19:19:34.551091425 +0000
+++ /tmp/new.6pUK8M 2026-07-27 19:19:34.551091425 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/dell-display-and-peripheral-manager/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/git-extensions/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/gnupg/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/google-earth-pro/windows.json=== Install Script (no changes) ===
=== Uninstall // 7e72e637 -> 51dc162a ===
--- /tmp/old.vzFD9r 2026-07-27 19:19:35.276106851 +0000
+++ /tmp/new.3mzb10 2026-07-27 19:19:35.276106851 +0000
@@ -65,4 +65,13 @@
Exit 1
}
+# Google Earth Pro's uninstaller spawns child msiexec processes; wait for them to finish
+$timeout = 120
+$elapsed = 0
+while ((Get-Process -Name "msiexec" -ErrorAction SilentlyContinue) -and ($elapsed -lt $timeout)) {
+ Start-Sleep -Seconds 2
+ $elapsed += 2
+ Write-Host "Waiting for msiexec to complete... ($elapsed seconds)"
+}
+
Exit $exitCodeee/maintained-apps/outputs/gpg4win/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/logitech-unifying-software/windows.json=== Install // f7bcd4ba -> a3795eea ===
--- /tmp/old.w5uCST 2026-07-27 19:19:35.550112680 +0000
+++ /tmp/new.amJXud 2026-07-27 19:19:35.550112680 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 9f1b824a -> 8ec563fd ===
--- /tmp/old.e4pvet 2026-07-27 19:19:35.566113021 +0000
+++ /tmp/new.J8YhN9 2026-07-27 19:19:35.566113021 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/logitune/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/rtools/windows.json=== Install // adeab869 -> fec8495e ===
--- /tmp/old.5iiCDO 2026-07-27 19:19:35.646114723 +0000
+++ /tmp/new.XsL30P 2026-07-27 19:19:35.646114723 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 6125a07b -> a289eb1d ===
--- /tmp/old.5y62E2 2026-07-27 19:19:35.662115063 +0000
+++ /tmp/new.tNAReb 2026-07-27 19:19:35.662115063 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/sonicwall-netextender/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/spyder/windows.json=== Install // 297c1c96 -> 6831586d ===
--- /tmp/old.MKXXeS 2026-07-27 19:19:35.942121021 +0000
+++ /tmp/new.SxcFWZ 2026-07-27 19:19:35.942121021 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 338688ef -> 1fe840b2 ===
--- /tmp/old.saSfdr 2026-07-27 19:19:35.958121361 +0000
+++ /tmp/new.0bPoct 2026-07-27 19:19:35.958121361 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/tightvnc/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/treesize-free/windows.json=== Install // 3e307826 -> 36e33a58 ===
--- /tmp/old.5DQY5h 2026-07-27 19:19:36.241127382 +0000
+++ /tmp/new.ZrkMy4 2026-07-27 19:19:36.241127382 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 3cc408af -> f316b604 ===
--- /tmp/old.SjGmXe 2026-07-27 19:19:36.257127723 +0000
+++ /tmp/new.riINjn 2026-07-27 19:19:36.257127723 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/yarn/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/zoom-outlook-plugin/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) === |
Verified each app's real registry DisplayName (winget AppsAndFeaturesEntries, MSI Property tables, vendor installer sources). Apps whose DisplayName carries a version/arch suffix used exact name matching, which silently matches nothing: - Added fuzzy_match_name to treesize-free (TreeSize Free V4.8.1), spyder (Spyder 6), git-extensions (Git Extensions 7.2.0.92), gpg4win (Gpg4win (5.0.2)), logitech-unifying-software (Logitech Unifying Software 2.52), and rtools (Rtools 4.5 (6768-6492)). - Fixed aomei-backupper-standard unique_identifier: the registry DisplayName is 'AOMEI Backupper' (no 'Standard' suffix since ~7.4), so the previous value matched nothing. Now also matches paid editions, which share the name. - Recategorized to match precedent: treesize-free & aomei -> Utilities; gnupg, gpg4win & sonicwall-netextender -> Security. - Removed the changes/ changelog entry (FMA additions aren't changelogged in the established Windows FMA PRs, and it double-counted apps from other PRs). Regenerated outputs; git-extensions (7.2.0.92) and gnupg (2.5.21) picked up their current winget versions in the process.
Detection queries verified against real registry DisplayNamesEvery app's identity query was verified against the actual Windows registry Add/Remove Programs DisplayName (osquery Switched to fuzzy name matching (DisplayName carries a version/arch suffix, so exact match silently matched nothing):
Fixed a broken identifier: AOMEI Backupper's registry DisplayName is Verified correct as exact match, no change: iTunes, Azure Data Studio, Dell Display and Peripheral Manager, Google Earth Pro, Logi Tune, SonicWall NetExtender, TightVNC ( Regenerating in the process pulled Git Extensions to 7.2.0.92 and GnuPG to 2.5.21 (their current winget versions). |
Script Diff Resultsee/maintained-apps/outputs/aomei-backupper-standard/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/apple-itunes/windows.json=== Install Script (no changes) ===
=== Uninstall // 5f74ea2b -> ac09716c ===
--- /tmp/old.YrgI12 2026-07-27 20:02:33.228943602 +0000
+++ /tmp/new.SfhOAJ 2026-07-27 20:02:33.229943606 +0000
@@ -30,4 +30,13 @@
if (-not $foundUninstaller) { Write-Host "Uninstaller for '$softwareName' not found."; Exit 1 }
} catch { Write-Host "Error: $_"; Exit 1 }
+# iTunes uses a WiX bundle that spawns child msiexec processes; wait for them to finish
+$timeout = 120
+$elapsed = 0
+while ((Get-Process -Name "msiexec" -ErrorAction SilentlyContinue) -and ($elapsed -lt $timeout)) {
+ Start-Sleep -Seconds 2
+ $elapsed += 2
+ Write-Host "Waiting for msiexec to complete... ($elapsed seconds)"
+}
+
Exit $exitCodeee/maintained-apps/outputs/azure-data-studio/windows.json=== Install // 1dc8cafc -> 622c4e10 ===
--- /tmp/old.RuAU04 2026-07-27 20:02:33.367944098 +0000
+++ /tmp/new.7puX8a 2026-07-27 20:02:33.367944098 +0000
@@ -13,7 +13,7 @@
Wait = $true
}
-$process = Start-Process @$processOptions
+$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Install exit code: $exitCode"
=== Uninstall // 87cf9389 -> 23fce27b ===
--- /tmp/old.N9yKAU 2026-07-27 20:02:33.382944152 +0000
+++ /tmp/new.qETz85 2026-07-27 20:02:33.382944152 +0000
@@ -23,7 +23,7 @@
Write-Host "Uninstall command: $uninstallCommand"; Write-Host "Uninstall args: $uninstallArgs"
$processOptions = @{ FilePath = $uninstallCommand; PassThru = $true; Wait = $true }
if ($uninstallArgs -ne '') { $processOptions.ArgumentList = $uninstallArgs }
- $process = Start-Process @$processOptions
+ $process = Start-Process @processOptions
$exitCode = $process.ExitCode; Write-Host "Uninstall exit code: $exitCode"; break
}
}ee/maintained-apps/outputs/dell-display-and-peripheral-manager/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/git-extensions/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/gnupg/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/google-earth-pro/windows.json=== Install Script (no changes) ===
=== Uninstall // 7e72e637 -> 51dc162a ===
--- /tmp/old.4PKcHO 2026-07-27 20:02:33.681945219 +0000
+++ /tmp/new.0EGfm7 2026-07-27 20:02:33.681945219 +0000
@@ -65,4 +65,13 @@
Exit 1
}
+# Google Earth Pro's uninstaller spawns child msiexec processes; wait for them to finish
+$timeout = 120
+$elapsed = 0
+while ((Get-Process -Name "msiexec" -ErrorAction SilentlyContinue) -and ($elapsed -lt $timeout)) {
+ Start-Sleep -Seconds 2
+ $elapsed += 2
+ Write-Host "Waiting for msiexec to complete... ($elapsed seconds)"
+}
+
Exit $exitCodeee/maintained-apps/outputs/gpg4win/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/logitech-unifying-software/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/logitune/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/rtools/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/sonicwall-netextender/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/spyder/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/tightvnc/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/treesize-free/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/yarn/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/zoom-outlook-plugin/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) === |
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** #50020 # What this does Adds **Azure Data Studio** as a Windows Fleet-maintained app. One of the 11 apps split out of #48501 that failed the FMA validator; #50016 shipped the 6 that passed. ## Why it was failing The install itself worked — the validator logged `New application detected at: C:\Program Files\Azure Data Studio`. The *script* never returned: ``` 20:08:19 INFO msg="Executing install script..." app="Azure Data Studio" 20:18:19 ERROR msg="Error executing install script: exit status 1" # exactly 10:00 later 20:18:19 INFO msg="New application detected at: C:\Program Files\Azure Data Studio" ``` Ten minutes on the nose is the validator's `executeScript` timeout. Azure Data Studio is a Visual Studio Code fork and ships the same Inno Setup script — including the **`runcode` task, which launches the app when the install finishes**. Because `Start-Process -Wait` waits for the process *and all of its descendants*, the launched app kept the script blocked forever. The fix is the switch VS Code's own FMA already uses: `/MERGETASKS=!runcode` (see [`vscode_install.ps1`](ee/maintained-apps/inputs/winget/scripts/vscode_install.ps1) and [`vscodium_install.ps1`](ee/maintained-apps/inputs/winget/scripts/vscodium_install.ps1), both of which pass validation). The script also waits on the installer process alone rather than its descendants, polls for the Add/Remove Programs entry, and stops a stray `azuredatastudio` process as a backstop in case a future build ignores the task suppression. ## Notes - Machine-scope x64 installer, per the winget manifest — Azure Data Studio publishes both user and machine scope, and Fleet installs run as SYSTEM, so machine scope is required. - Clean ARP `DisplayName` (`Azure Data Studio`), so exact name matching. Publisher `Microsoft Corporation`. - Uninstall is unchanged: the Inno uninstaller doesn't leave anything resident, and `-Wait` waiting on descendants is the desired behavior there (Inno relaunches itself from `%TEMP%`). - Ships a new catalog icon and website asset. # Checklist for submitter - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. - [x] Timeouts are implemented and retries are limited to avoid infinite loops ## Testing - [x] FMA CI validator (install → detect → uninstall) **passes** on the SYSTEM-context Windows runner — [run 30384162280](https://github.com/fleetdm/fleet/actions/runs/30384162280) (`All checks passed`) - [x] Generated output verified locally: manifest SHA matches the winget manifest, exists/patched queries reviewed for name + publisher correctness, `apps.json` is valid JSON with a description filled in. - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added Azure Data Studio to the available Windows software catalog. * Added support for installing and uninstalling Azure Data Studio (version 1.52.0) via silent installer and uninstaller flows with completion detection. * Added an Azure Data Studio icon to the software interface for better visual identification. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** #50020 # What this does Adds **GNU Privacy Guard** as a Windows Fleet-maintained app. One of the 11 apps split out of #48501 that failed the FMA validator; #50016 shipped the 6 that passed. ## Why it was failing The install itself worked — the validator logged `New application detected at: C:\Program Files\GnuPG`. The *script* never returned: ``` 20:18:36 INFO msg="Executing install script..." app="GNU Privacy Guard" 20:28:36 ERROR msg="Error executing install script: exit status 1" # exactly 10:00 later 20:28:36 INFO msg="New application detected at: C:\Program Files\GnuPG" ``` Ten minutes on the nose is the validator's `executeScript` timeout. The cause is a PowerShell detail rather than anything wrong with the installer: **`Start-Process -Wait` waits for the process *and all of its descendants***. GnuPG's installer starts `gpg-agent`, `dirmngr`, `keyboxd` and `scdaemon` and leaves them resident, so `-Wait` never returns. The same run left the installer `.exe` locked in the validator's temp dir, which is the other tell that a child process was still alive. The install script now follows the pattern already established by [`ollama_install.ps1`](ee/maintained-apps/inputs/winget/scripts/ollama_install.ps1): start with `-PassThru` (no `-Wait`), wait on the installer process alone with a 7-minute cap (below the caller's 10-minute script budget), poll for the Add/Remove Programs entry so a fast-returning installer can't be mistaken for a finished one, then stop the daemons. Stopping the daemons also fixes the uninstall, which would otherwise fail on files those processes hold open. The uninstall script stops them up front, uses NSIS's `_?=<dir>` switch so the uninstaller runs in place instead of relaunching itself detached from `%TEMP%`, and polls the ARP key to confirm removal. ## Notes - Clean ARP `DisplayName` (`GNU Privacy Guard`), so exact name matching — no `fuzzy_match_name` needed. Publisher `The GnuPG Project`. - Ships a new catalog icon and website asset. # Checklist for submitter - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. - [x] Timeouts are implemented and retries are limited to avoid infinite loops ## Testing - [x] FMA CI validator (install → detect → uninstall) **passes** on the SYSTEM-context Windows runner — [run 30384069714](https://github.com/fleetdm/fleet/actions/runs/30384069714) (`All checks passed`) - [x] Generated output verified locally: manifest SHA matches the winget manifest, exists/patched queries reviewed for name + publisher correctness, `apps.json` is valid JSON with a description filled in. - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added GNU Privacy Guard as a supported Windows application in the maintained apps catalog. * Added install/upgrade detection and uninstall support for Windows. * Added GNU Privacy Guard to the software catalog (Security category). * Added a dedicated GNU Privacy Guard icon to the software interface for proper name-based display. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** #50020 # What this does Adds **Logitech Unifying Software** as a Windows Fleet-maintained app. One of the 11 apps split out of #48501 that failed the FMA validator; #50016 shipped the 6 that passed. ## Why it was failing Install and detection were already fine on the SYSTEM-context Windows runner — osquery found `Logitech Unifying Software 2.52` at `C:\Program Files\Common Files\LogiShrd\Unifying`. **Uninstall** was the failure: ``` 20:40:55 INFO msg="Executing uninstall script for app..." 20:40:57 INFO msg="Found app: 'Logitech Unifying Software 2.52' ... Version: 2.52.33" 20:40:57 ERROR msg="App still present after uninstall (expected no match for version '2.52.33' in programs)" ``` Two seconds start to finish — the uninstaller hadn't actually done anything yet. This is standard NSIS behavior: the uninstaller copies itself to `%TEMP%` and relaunches, so the process the script starts exits almost immediately while the real work happens in a detached child. The fix passes NSIS's `_?=<dir>` switch, which runs the uninstaller in place instead of relaunching, making it synchronous. It has to be the last argument and unquoted, so the script builds a single argument string rather than an array (PowerShell would quote an element containing spaces). A bounded poll on the ARP key follows as a backstop, and the script fails explicitly if the entry is still there. ## Notes - **Versioned ARP name.** The registry `DisplayName` is `Logitech Unifying Software 2.52`, so the input uses `fuzzy_match_name` and the exists query is `name LIKE 'Logitech Unifying Software %'`. The uninstall script matches the same prefix rather than an exact string. - Publisher `Logitech` confirmed against the winget locale manifest. - Installs under `C:\Program Files\Common Files`, so the validator's "no changes detected in `C:\Program Files`" line is an expected warning, not a failure. - Ships a new catalog icon and website asset. # Checklist for submitter - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. - [x] Timeouts are implemented and retries are limited to avoid infinite loops ## Testing - [x] FMA CI validator (install → detect → uninstall) **passes** on the SYSTEM-context Windows runner — [run 30384010810](https://github.com/fleetdm/fleet/actions/runs/30384010810) (`All checks passed`) - [x] Generated output verified locally: manifest SHA matches the winget manifest, exists/patched queries reviewed for name + publisher correctness, `apps.json` is valid JSON with a description filled in. - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added Logitech Unifying Software to the Windows software catalog, including the version 2.52.33 download, checksum, and install-detection metadata. * Implemented silent installation and a robust, registry-aware uninstall flow (with process lock handling and timeout behavior). * Added a dedicated Logitech Unifying Software icon to the software page UI. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** #50020 # What this does Adds **Google Earth Pro** as a Windows Fleet-maintained app (a Windows counterpart to the existing `google-earth-pro/darwin` FMA). One of the 11 apps split out of #48501 that failed the FMA validator; #50016 shipped the 6 that passed. ## Why it was failing Install and detection were already fine on the SYSTEM-context Windows runner — osquery found `Google Earth Pro` 7.3.7.1155. **Uninstall** was the failure: ``` INFO msg="Executing uninstall script for app..." app="Google Earth Pro" INFO msg="Found app: 'Google Earth Pro' at , Version: 7.3.7.1155" ERROR msg="App still present after uninstall (expected no match for version '7.3.7.1155' in programs)" ``` The EXE wraps a WiX MSI, so the ARP `UninstallString` is `MsiExec.exe /X{ProductCode}` — with **no quiet switch**. The old script ran that string verbatim, which raises a confirmation dialog in session 0 where nothing can click it, so the uninstall silently no-ops. The uninstall script now resolves the MSI product code (from the `UninstallString`, falling back to the registry key name) and runs `msiexec /x <code> /quiet /norestart` with a bounded 5-minute wait, then drains child `msiexec` processes. `3010`/`1641` are treated as success. ## Notes - **Identity verified against the real installer**, not winget metadata. The installer's embedded MSI Property table reads: `ProductName` = `Google Earth Pro`, `Manufacturer` = `Google`, `ProductVersion` = `7.3.7.1155`, `ALLUSERS` = `1`, `ProductCode` = `{E3B69BB6-FFD8-441C-933E-BB8A3136ED8F}`. No `ARPSYSTEMCOMPONENT`, so it is not a bootstrapper. That confirms `unique_identifier` = `Google Earth Pro` and the exists-query publisher `Google` (not "Google LLC"). - Installs to `C:\Program Files (x86)`, so the validator's "no changes detected in `C:\Program Files`" line is an expected warning, not a failure. - Reuses the existing `google earth pro` catalog icon — no new icon needed. # Checklist for submitter - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. - [x] Timeouts are implemented and retries are limited to avoid infinite loops ## Testing - [x] FMA CI validator (install → detect → uninstall) **passes** on the SYSTEM-context Windows runner — [run 30383934805](https://github.com/fleetdm/fleet/actions/runs/30383934805) (`All checks passed`) - [x] Generated output verified locally: manifest SHA matches the winget manifest, exists/patched queries checked against the MSI Property table, `apps.json` is valid JSON with a description filled in. - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added Google Earth Pro for Windows to the maintained app catalog. * Added maintained-apps install and uninstall support for Google Earth Pro (version 7.3.7.1155). * Included automated download integrity verification and detection logic for installed/updated versions. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** #50020 # What this does Adds **Rtools** as a Windows Fleet-maintained app. One of the 11 apps split out of #48501 that failed the FMA validator; #50016 shipped the 6 that passed. ## Why it was failing The install script hit the validator's 10-minute `executeScript` cap exactly: ``` 20:41:22 INFO msg="Executing install script..." app=Rtools 20:51:22 ERROR msg="Error executing install script: exit status 1" # exactly 10:00 later 20:51:22 WARN msg="failed to remove rtools45-6768-6492.exe: ... Access is denied." ``` The locked installer in the temp dir shows a process was still alive. `Start-Process -Wait` waits for the process *and all of its descendants*, which is the same root cause as the other install-timeout apps in this batch. Rtools is also the one app in the batch where a **slow unpack** is a plausible second cause — the installer is ~460 MB and expands a full toolchain. So rather than assume, the script now waits on the installer process alone with a 480s cap (under the caller's 10-minute budget) and logs elapsed time plus Add/Remove Programs registration state on every poll. If the cap is reached: - **registered** → the install finished and only a lingering child remains, so it stops that process and succeeds; - **not registered** → the unpack genuinely didn't finish, and it fails with that stated explicitly. Either way the CI log now says which one happened instead of just timing out. ## Notes - **Identity verified against the installer**, not winget metadata. The setup stub's PE version resource reads `CompanyName: The R Foundation`, `ProductName: Rtools`. Inno derives `VersionInfoCompany` from `AppPublisher`, so the ARP publisher is `The R Foundation` — which is what the exists query uses. - **Versioned ARP name.** The registry `DisplayName` is `Rtools 4.5 (6768-6492)`, so the input uses `fuzzy_match_name` and the exists query is `name LIKE 'Rtools %'`. - Installs to `C:\rtools45`, not Program Files, so the validator's "no changes detected in `C:\Program Files`" line is an expected warning, not a failure. - Ships a new catalog icon and website asset. # Checklist for submitter - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. - [x] Timeouts are implemented and retries are limited to avoid infinite loops ## Testing - [x] FMA CI validator (install → detect → uninstall) **passes** on the SYSTEM-context Windows runner — [run 30384196159](https://github.com/fleetdm/fleet/actions/runs/30384196159) (`All checks passed`) - [x] Generated output verified locally: manifest SHA matches the winget manifest, exists/patched queries checked against the installer's PE version resource, `apps.json` is valid JSON with a description filled in. - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added Rtools as a supported Windows application. * Added installation and uninstallation support with silent setup and silent removal. * Added Rtools version metadata, installer verification, and Developer tools categorization. * Added a dedicated Rtools icon for software listings. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** #50020 # What this does Adds **Gpg4win** as a Windows Fleet-maintained app. One of the 11 apps split out of #48501 that failed the FMA validator; #50016 shipped the 6 that passed. ## Why it was failing Same root cause as GNU Privacy Guard (#50025) — Gpg4win bundles GnuPG. The install worked; the *script* never returned: ``` 20:30:53 INFO msg="Executing install script..." app=Gpg4win 20:40:53 ERROR msg="Error executing install script: exit status 1" # exactly 10:00 later 20:40:53 INFO msg="New application detected at: C:\Program Files\Gpg4win" ``` Ten minutes on the nose is the validator's `executeScript` timeout. **`Start-Process -Wait` waits for the process *and all of its descendants***, and Gpg4win leaves `gpg-agent`, `dirmngr`, `keyboxd` and `scdaemon` resident (plus Kleopatra), so `-Wait` never returns. The same run left `gpg4win-5.0.2.exe` locked in the validator's temp dir, confirming a live child process. The install script now follows the pattern already established by [`ollama_install.ps1`](ee/maintained-apps/inputs/winget/scripts/ollama_install.ps1): start with `-PassThru` (no `-Wait`), wait on the installer process alone with a 7-minute cap (below the caller's 10-minute script budget), poll for the Add/Remove Programs entry, then stop the leftovers. The uninstall script stops those processes up front (they hold file locks that make the uninstall fail), uses NSIS's `_?=<dir>` switch so the uninstaller runs in place rather than relaunching itself detached from `%TEMP%`, and polls the ARP key to confirm removal. ## Notes - **Versioned ARP name.** The registry `DisplayName` is `Gpg4win (5.0.2)`, so the input uses `fuzzy_match_name` and the exists query is `name LIKE 'Gpg4win %'`. The uninstall script matches the same prefix. - x86-only installer. Publisher `The Gpg4win Project`. - Ships a new catalog icon and website asset. # Checklist for submitter - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. - [x] Timeouts are implemented and retries are limited to avoid infinite loops ## Testing - [x] FMA CI validator (install → detect → uninstall) **passes** on the SYSTEM-context Windows runner — [run 30384125610](https://github.com/fleetdm/fleet/actions/runs/30384125610) (`All checks passed`) - [x] Generated output verified locally: manifest SHA matches the winget manifest, exists/patched queries reviewed for name + publisher correctness, `apps.json` is valid JSON with a description filled in. - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added Gpg4win as a supported Windows application. - Added Gpg4win version 5.0.2 with Security categorization. - Added a Gpg4win icon to the software interface. - Introduced silent install and uninstall support with process cleanup, timeouts, and registry-based verification to confirm install/removal outcomes. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** #50020 # What this does Adds **AOMEI Backupper Standard** as a Windows Fleet-maintained app. One of the 11 apps split out of #48501 that failed the FMA validator; #50016 shipped the 6 that passed. ## Why it was failing Install and detection were already fine on the SYSTEM-context Windows runner — the validator installed it and osquery found `AOMEI Backupper` 8.4.0. **Uninstall** was the failure: ``` ERROR msg="Error uninstalling app: exit status 1" app="AOMEI Backupper Standard" ERROR msg="Output: Uninstaller for 'AOMEI Backupper Standard' not found." ``` AOMEI unified the ARP `DisplayName` across editions around v7.4 — the registry entry reads `AOMEI Backupper`, with no `Standard` suffix. The uninstall script searched for the catalog name and matched nothing. `unique_identifier` was already corrected to `AOMEI Backupper`; this fixes the uninstall script to match. ## Notes - **Edition matching.** `AOMEI Backupper` also matches the paid Pro/Workstation/Server editions — AOMEI shares the DisplayName across editions and no registry value distinguishes them. Detecting the free edition specifically isn't possible from inventory. - **Non-pinned installer URL.** `https://www2.aomeisoftware.com/download/adb/AOMEIBackupperStd.exe` is a "latest" URL, so the pinned SHA will drift when AOMEI ships a new build until the FMA auto-update bumps it. - x86-only installer, so it lands in `C:\Program Files (x86)`. The validator's "no changes detected in `C:\Program Files`" line is an expected warning, not a failure. # Checklist for submitter - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. - [x] Timeouts are implemented and retries are limited to avoid infinite loops ## Testing - [x] FMA CI validator (install → detect → uninstall) **passes** on the SYSTEM-context Windows runner — [run 30383902487](https://github.com/fleetdm/fleet/actions/runs/30383902487) (`All checks passed`) - [x] Generated output verified locally: manifest SHA matches the winget manifest, exists/patched queries reviewed for name + publisher correctness, `apps.json` is valid JSON with a description filled in. - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added **AOMEI Backupper Standard** (version **8.4.0.0.0**) to the Windows software catalog, including verified installer download (SHA-256). - Introduced dedicated silent **install** and **uninstall** support, with version gating and idempotent uninstall behavior when the app isn’t present. - Added a **new software icon** and updated the listing so the correct icon now appears for this product. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Allen Houchins <allenhouchins@mac.com>
Related issue: N/A — Windows Fleet-maintained app (FMA) coverage for apps found deployed in a customer's ManageEngine SDP environment but missing from Fleet.
What this does
Adds 17 Windows Fleet-maintained apps. Each app has a winget-sourced input, a generated output manifest, and (where a cleanly-licensed ≥256px logo was found) a catalog icon. Detection identity was verified against each app's real registry DisplayName; apps whose DisplayName carries a version/arch suffix use fuzzy name matching, the rest match exactly.
MSI (clean, auto upgrade-code uninstall):
Git Extensions 7.2.0.92) → fuzzy matchEXE — Inno Setup (custom
/VERYSILENTinstall + registry-lookup uninstall):TreeSize Free V4.8.1) → fuzzy matchRtools 4.5 (6768-6492)) → fuzzy matchAOMEI Backupper(no "Standard" suffix); x86-onlyEXE — NSIS (custom
/Sinstall + registry-lookup uninstall):Gpg4win (5.0.2)) → fuzzy match; x86-onlyLogitech Unifying Software 2.52) → fuzzy matchSpyder 6) → fuzzy matchEXE — WiX bundle / burn (custom install + bundle uninstall):
iTunes) → exact match; reuses the existingItunesiconLogi Tune→ exact matchEXE — vendor installer:
/Silent) and Google Earth Pro (OMAHA=1, ships an embedded MSI) — clean ARP names → exact matchNot in this batch
mainvia separate PRs (e.g. Add WinDirStat as a Windows FMA #48762) and merged in, so they're no longer net-new here.Notes
unique_identifier(registry DisplayName / osqueryprograms.name) and publisher were verified per thenew-fmaskill against wingetAppsAndFeaturesEntries, MSI Property tables (msiinfo), and vendor installer scripts — not assumed. This corrected two silent no-match bugs: the six fuzzy-match apps above, and AOMEI Backupper, whoseunique_identifierwasAOMEI Backupper Standard(a string the registry never contains since ~v7.4).AOMEI Backuppername also matches the paid Pro/Workstation/Server editions — AOMEI unified the ARP DisplayName across editions, and no registry value distinguishes them. Detecting the free edition (vs. nothing) is the intended tradeoff.Itunesicon, and Google Earth Pro, Logi Tune, and Spyder match icons already in the frontend.Testing
go test ./ee/maintained-apps/...passes.