diff --git a/ee/maintained-apps/inputs/winget/microsoft-dotnet-desktop-runtime-10.json b/ee/maintained-apps/inputs/winget/microsoft-dotnet-desktop-runtime-10.json new file mode 100644 index 0000000000..e986046f41 --- /dev/null +++ b/ee/maintained-apps/inputs/winget/microsoft-dotnet-desktop-runtime-10.json @@ -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"] +} diff --git a/ee/maintained-apps/outputs/apps.json b/ee/maintained-apps/outputs/apps.json index 1a70f44b18..ba1396de85 100644 --- a/ee/maintained-apps/outputs/apps.json +++ b/ee/maintained-apps/outputs/apps.json @@ -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", diff --git a/ee/maintained-apps/outputs/microsoft-dotnet-desktop-runtime-10/windows.json b/ee/maintained-apps/outputs/microsoft-dotnet-desktop-runtime-10/windows.json new file mode 100644 index 0000000000..c1a829a8aa --- /dev/null +++ b/ee/maintained-apps/outputs/microsoft-dotnet-desktop-runtime-10/windows.json @@ -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" + } +} diff --git a/frontend/pages/SoftwarePage/components/icons/index.ts b/frontend/pages/SoftwarePage/components/icons/index.ts index 83f58243c2..4aa9b0f9cc 100644 --- a/frontend/pages/SoftwarePage/components/icons/index.ts +++ b/frontend/pages/SoftwarePage/components/icons/index.ts @@ -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, diff --git a/website/assets/images/app-icon-microsoft-dotnet-desktop-runtime-10-60x60@2x.png b/website/assets/images/app-icon-microsoft-dotnet-desktop-runtime-10-60x60@2x.png new file mode 100644 index 0000000000..55378b5ce4 Binary files /dev/null and b/website/assets/images/app-icon-microsoft-dotnet-desktop-runtime-10-60x60@2x.png differ