Add Microsoft .NET Desktop Runtime 10 as a Windows FMA (#50361)
**Related issue:** Resolves #50360 Adds Microsoft .NET Desktop Runtime 10 as a Windows Fleet-maintained app, from winget `Microsoft.DotNet.DesktopRuntime.10` (10.0.10, WiX burn bundle, x64). This closes the gap opened by HandBrake (#50323 / #50352). HandBrake requires the .NET **Desktop** Runtime and its install script now hard-fails without it, but Fleet had no FMA that could satisfy that — we ship `microsoft-dotnet-runtime-8`/`-10`, which are the *base* runtime, a different package with its own Add/Remove Programs entry. The customer's ManageEngine catalog also deploys the Desktop Runtime directly. ## Verification The winget manifest supplies `AppsAndFeaturesEntries`, and I confirmed each value against the real installer by extracting the burn bundle's registration data: ``` Microsoft Windows Desktop Runtime 10.0.10 (x64) Publisher="Microsoft Corporation" Version="10.0.10.50000" ``` - Installer SHA confirmed against a local download (`e82fc901…84d1`). - The `DisplayName` carries both version and architecture, so the exists query uses the same `LIKE 'Microsoft Windows Desktop Runtime 10.%' AND name LIKE '%(x64)'` shape as the existing base-runtime FMAs. - The bundle exposes several ProductCodes (the bundle plus its MSI components), which is exactly the shape the existing uninstall script already documents and handles. **`use_display_version_for_patch` is required here.** The registry `DisplayVersion` is `10.0.10.50000` but the winget package version is `10.0.10`. Without the flag the patch policy would compare against the marketing version and mis-order against what osquery reports. The generated patched query correctly compares against `10.0.10.50000`. ## Reuse rather than duplication - **Scripts:** this reuses `microsoft_dotnet_runtime_install.ps1` / `_uninstall.ps1` unchanged. The Desktop Runtime is the same burn bundle shape, and the uninstaller already resolves the bundle from the injected `$PACKAGE_ID` with a Package Cache fallback. Those scripts are already shared by the two base-runtime FMAs, so this follows the existing pattern rather than adding a near-identical copy. - **Icon:** reuses the existing `MicrosoftDotnetRuntime` component and its `.NET` artwork. The burn bundle only carries a 32×32 icon, so extracting one would have meant shipping a blurry upscale of the same logo. The new map key is `"microsoft .net desktop runtime"` (no version). Icon lookup is a loose *prefix* match — `s === key || s.startsWith(key + " ")` — so one key covers 10 and any future major, mirroring how `"microsoft .net runtime"` already serves both base-runtime FMAs. It is longer than that key, and lookup sorts longest-first, so the desktop runtime cannot be mis-matched to the base runtime icon. # Checklist for submitter - [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 Microsoft .NET Desktop Runtime 10 to the Windows software catalog. * Added support for installing and uninstalling the x64 desktop runtime, including version detection and reboot handling. * Added a dedicated Microsoft .NET Runtime icon for the software listing. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "Microsoft .NET Desktop Runtime 10",
|
||||
"slug": "microsoft-dotnet-desktop-runtime-10/windows",
|
||||
"package_identifier": "Microsoft.DotNet.DesktopRuntime.10",
|
||||
"unique_identifier": "Microsoft Windows Desktop Runtime",
|
||||
"exists_query": "SELECT 1 FROM programs WHERE name LIKE 'Microsoft Windows Desktop Runtime 10.%' AND name LIKE '%(x64)' AND publisher = 'Microsoft Corporation';",
|
||||
"installer_arch": "x64",
|
||||
"installer_type": "exe",
|
||||
"installer_scope": "",
|
||||
"use_display_version_for_patch": true,
|
||||
"install_script_path": "ee/maintained-apps/inputs/winget/scripts/microsoft_dotnet_runtime_install.ps1",
|
||||
"uninstall_script_path": "ee/maintained-apps/inputs/winget/scripts/microsoft_dotnet_runtime_uninstall.ps1",
|
||||
"default_categories": ["Developer tools"]
|
||||
}
|
||||
@@ -5398,6 +5398,13 @@
|
||||
"unique_identifier": "com.microsoft.StorageExplorer",
|
||||
"description": "Microsoft Azure Storage Explorer is an explorer for Azure Storage."
|
||||
},
|
||||
{
|
||||
"name": "Microsoft .NET Desktop Runtime 10",
|
||||
"slug": "microsoft-dotnet-desktop-runtime-10/windows",
|
||||
"platform": "windows",
|
||||
"unique_identifier": "Microsoft Windows Desktop Runtime",
|
||||
"description": "Microsoft .NET Desktop Runtime 10 runs desktop apps built on .NET 10, including Windows Forms and WPF apps."
|
||||
},
|
||||
{
|
||||
"name": "Microsoft .NET Runtime 10",
|
||||
"slug": "microsoft-dotnet-runtime-10/windows",
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "10.0.10",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM programs WHERE name LIKE 'Microsoft Windows Desktop Runtime 10.%' AND name LIKE '%(x64)' AND publisher = 'Microsoft Corporation';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name LIKE 'Microsoft Windows Desktop Runtime 10.%' AND name LIKE '%(x64)' AND publisher = 'Microsoft Corporation' AND version_compare(version, '10.0.10.50000') < 0);"
|
||||
},
|
||||
"installer_url": "https://builds.dotnet.microsoft.com/dotnet/WindowsDesktop/10.0.10/windowsdesktop-runtime-10.0.10-win-x64.exe",
|
||||
"install_script_ref": "13facdef",
|
||||
"uninstall_script_ref": "661ee74e",
|
||||
"sha256": "e82fc901c8f52d716293b2bc0830ce0dd254a06268c457a19e8fc503560a84d1",
|
||||
"default_categories": [
|
||||
"Developer tools"
|
||||
]
|
||||
}
|
||||
],
|
||||
"refs": {
|
||||
"13facdef": "# Learn more about .exe install scripts:\n# http://fleetdm.com/learn-more-about/exe-install-scripts\n#\n# The .NET Runtime ships as a WiX \"burn\" bootstrapper (.exe). It installs\n# machine-wide and registers its own ARP entry. Silent switches come from the\n# winget installer manifest (Silent: /quiet, Custom: /norestart).\n\n$exeFilePath = \"${env:INSTALLER_PATH}\"\n\ntry {\n if (-not (Test-Path $exeFilePath)) {\n Write-Host \"Error: Installer file not found at: $exeFilePath\"\n Exit 1\n }\n\n $processOptions = @{\n FilePath = \"$exeFilePath\"\n ArgumentList = \"/quiet /norestart\"\n PassThru = $true\n Wait = $true\n NoNewWindow = $true\n }\n\n $process = Start-Process @processOptions\n $exitCode = $process.ExitCode\n Write-Host \"Install exit code: $exitCode\"\n\n # 0 = success, 3010 = success but reboot required, 1641 = reboot initiated\n if ($exitCode -eq 3010 -or $exitCode -eq 1641) {\n Exit 0\n }\n\n Exit $exitCode\n\n} catch {\n Write-Host \"Error: $_\"\n Exit 1\n}\n",
|
||||
"661ee74e": "# Uninstalls the Microsoft .NET Runtime WiX \"burn\" bundle.\n#\n# The runtime installs as a burn bootstrapper that registers a *bundle* ARP entry\n# (keyed by the bundle ProductCode) alongside several MSI component entries that\n# share the same DisplayName. Only the bundle entry removes the whole runtime, and\n# it uninstalls by running its cached bootstrapper .exe with /uninstall -- never via\n# msiexec (see https://silentinstallhq.com/net-runtime-8-0-silent-uninstall-powershell/).\n# We target the bundle by its ProductCode (injected by the ingester) and fall back\n# to the cached bootstrapper in the Package Cache.\n\n$productCode = '{866BECDA-F284-473A-9E84-0CCE816BF06F}'\n\nfunction Invoke-Uninstaller {\n param([string]$exe, [string]$exeArgs)\n if ($exeArgs -notmatch '/uninstall') { $exeArgs = \"/uninstall $exeArgs\" }\n if ($exeArgs -notmatch '/quiet') { $exeArgs = \"$exeArgs /quiet\" }\n if ($exeArgs -notmatch '/norestart') { $exeArgs = \"$exeArgs /norestart\" }\n $exeArgs = $exeArgs.Trim()\n Write-Host \"Uninstall command: $exe\"\n Write-Host \"Uninstall args: $exeArgs\"\n $process = Start-Process -FilePath $exe -ArgumentList $exeArgs -NoNewWindow -PassThru -Wait\n return $process.ExitCode\n}\n\n$exitCode = $null\n\n# 1) Preferred: the bundle ARP entry, looked up by the bundle ProductCode. Its\n# UninstallString/QuietUninstallString points to the cached bootstrapper .exe.\n$keys = @(\n \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\$productCode\",\n \"HKLM:\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\$productCode\"\n)\n\nforeach ($key in $keys) {\n if (-not (Test-Path $key)) { continue }\n $entry = Get-ItemProperty $key -ErrorAction SilentlyContinue\n if (-not $entry) { continue }\n\n $raw = $entry.QuietUninstallString\n if (-not $raw) { $raw = $entry.UninstallString }\n if (-not $raw) { continue }\n\n # Parse into executable + args, handling quoted/unquoted/bare shapes.\n if ($raw -match '^\\s*\"([^\"]+)\"\\s*(.*)$') {\n $exe = $matches[1]; $exeArgs = $matches[2].Trim()\n } elseif ($raw -match '(?i)^\\s*(.+?\\.exe)\\s*(.*)$') {\n $exe = $matches[1]; $exeArgs = $matches[2].Trim()\n } else {\n $exe = $raw; $exeArgs = \"\"\n }\n\n $exitCode = Invoke-Uninstaller -exe $exe -exeArgs $exeArgs\n break\n}\n\n# 2) Fallback: run the cached bootstrapper directly from the Package Cache, which\n# burn names after the bundle ProductCode.\nif ($null -eq $exitCode) {\n $cached = Get-ChildItem -Path \"C:\\ProgramData\\Package Cache\\$productCode\" -Filter *.exe -ErrorAction SilentlyContinue | Select-Object -First 1\n if ($cached) {\n $exitCode = Invoke-Uninstaller -exe $cached.FullName -exeArgs \"\"\n }\n}\n\nif ($null -eq $exitCode) {\n Write-Host \"Uninstall entry not found for product code: $productCode\"\n Exit 0\n}\n\nWrite-Host \"Uninstall exit code: $exitCode\"\n# 0 = success, 3010 = success but reboot required, 1641 = reboot initiated\nif ($exitCode -eq 3010 -or $exitCode -eq 1641) { Exit 0 }\nExit $exitCode\n"
|
||||
}
|
||||
}
|
||||
@@ -1792,6 +1792,7 @@ export const SOFTWARE_NAME_TO_ICON_MAP = {
|
||||
"menubar stats": MenubarStats,
|
||||
menubarx: Menubarx,
|
||||
"merlin project": MerlinProject,
|
||||
"microsoft .net desktop runtime": MicrosoftDotnetRuntime,
|
||||
"microsoft .net runtime": MicrosoftDotnetRuntime,
|
||||
"microsoft 365 copilot": Microsoft365Copilot,
|
||||
"microsoft auto update": MicrosoftAutoUpdate,
|
||||
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
Reference in New Issue
Block a user