Add VC++ Redistributable (x64) as a Windows FMA (#46935)
Add support for Microsoft Visual C++ Redistributable (x64) via winget: new installer and uninstaller PowerShell scripts that handle the WiX "burn" bootstrapper, a winget input manifest, an app entry in outputs/apps.json, and a detailed outputs/vc-redist-x64/windows.json with version metadata (14.51.36231.0), installer URL, SHA256 and embedded script refs. The uninstall script targets the bundle ProductCode (falls back to the Package Cache) and normalizes /uninstall, /quiet and /norestart handling; the install script runs the bootstrapper with /quiet /norestart and treats reboot codes (3010, 1641) as success.
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
# Learn more about .exe install scripts:
|
||||
# http://fleetdm.com/learn-more-about/exe-install-scripts
|
||||
#
|
||||
# The Visual C++ Redistributable ships as a WiX "burn" bootstrapper (.exe). It
|
||||
# installs machine-wide and registers its own ARP entry. Silent switches come
|
||||
# from the winget installer manifest (burn bundles use /quiet /norestart).
|
||||
|
||||
$exeFilePath = "${env:INSTALLER_PATH}"
|
||||
|
||||
try {
|
||||
if (-not (Test-Path $exeFilePath)) {
|
||||
Write-Host "Error: Installer file not found at: $exeFilePath"
|
||||
Exit 1
|
||||
}
|
||||
|
||||
$processOptions = @{
|
||||
FilePath = "$exeFilePath"
|
||||
ArgumentList = "/quiet /norestart"
|
||||
PassThru = $true
|
||||
Wait = $true
|
||||
NoNewWindow = $true
|
||||
}
|
||||
|
||||
$process = Start-Process @processOptions
|
||||
$exitCode = $process.ExitCode
|
||||
Write-Host "Install exit code: $exitCode"
|
||||
|
||||
# 0 = success, 3010 = success but reboot required, 1641 = reboot initiated
|
||||
if ($exitCode -eq 3010 -or $exitCode -eq 1641) {
|
||||
Exit 0
|
||||
}
|
||||
|
||||
Exit $exitCode
|
||||
|
||||
} catch {
|
||||
Write-Host "Error: $_"
|
||||
Exit 1
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
# Uninstalls the Microsoft Visual C++ Redistributable WiX "burn" bundle.
|
||||
#
|
||||
# The redistributable installs as a burn bootstrapper that registers a *bundle*
|
||||
# ARP entry (keyed by the bundle ProductCode) alongside several MSI component
|
||||
# entries ("...X64 Minimum Runtime...", "...Additional Runtime..."). Only the
|
||||
# bundle entry removes the whole redistributable, and it uninstalls by running
|
||||
# its cached bootstrapper .exe with /uninstall -- never via msiexec. We target
|
||||
# the bundle by its ProductCode (injected by the ingester) and fall back to the
|
||||
# cached bootstrapper in the Package Cache.
|
||||
|
||||
$productCode = ${PACKAGE_ID}
|
||||
|
||||
function Invoke-Uninstaller {
|
||||
param([string]$exe, [string]$exeArgs)
|
||||
if ($exeArgs -notmatch '/uninstall') { $exeArgs = "/uninstall $exeArgs" }
|
||||
if ($exeArgs -notmatch '/quiet') { $exeArgs = "$exeArgs /quiet" }
|
||||
if ($exeArgs -notmatch '/norestart') { $exeArgs = "$exeArgs /norestart" }
|
||||
$exeArgs = $exeArgs.Trim()
|
||||
Write-Host "Uninstall command: $exe"
|
||||
Write-Host "Uninstall args: $exeArgs"
|
||||
$process = Start-Process -FilePath $exe -ArgumentList $exeArgs -NoNewWindow -PassThru -Wait
|
||||
return $process.ExitCode
|
||||
}
|
||||
|
||||
$exitCode = $null
|
||||
|
||||
# 1) Preferred: the bundle ARP entry, looked up by the bundle ProductCode. Its
|
||||
# UninstallString/QuietUninstallString points to the cached bootstrapper .exe.
|
||||
$keys = @(
|
||||
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$productCode",
|
||||
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\$productCode"
|
||||
)
|
||||
|
||||
foreach ($key in $keys) {
|
||||
if (-not (Test-Path $key)) { continue }
|
||||
$entry = Get-ItemProperty $key -ErrorAction SilentlyContinue
|
||||
if (-not $entry) { continue }
|
||||
|
||||
$raw = $entry.QuietUninstallString
|
||||
if (-not $raw) { $raw = $entry.UninstallString }
|
||||
if (-not $raw) { continue }
|
||||
|
||||
# Parse into executable + args, handling quoted/unquoted/bare shapes.
|
||||
if ($raw -match '^\s*"([^"]+)"\s*(.*)$') {
|
||||
$exe = $matches[1]; $exeArgs = $matches[2].Trim()
|
||||
} elseif ($raw -match '(?i)^\s*(.+?\.exe)\s*(.*)$') {
|
||||
$exe = $matches[1]; $exeArgs = $matches[2].Trim()
|
||||
} else {
|
||||
$exe = $raw; $exeArgs = ""
|
||||
}
|
||||
|
||||
$exitCode = Invoke-Uninstaller -exe $exe -exeArgs $exeArgs
|
||||
break
|
||||
}
|
||||
|
||||
# 2) Fallback: run the cached bootstrapper directly from the Package Cache, which
|
||||
# burn names after the bundle ProductCode.
|
||||
if ($null -eq $exitCode) {
|
||||
$cached = Get-ChildItem -Path "C:\ProgramData\Package Cache\$productCode" -Filter *.exe -ErrorAction SilentlyContinue | Select-Object -First 1
|
||||
if ($cached) {
|
||||
$exitCode = Invoke-Uninstaller -exe $cached.FullName -exeArgs ""
|
||||
}
|
||||
}
|
||||
|
||||
if ($null -eq $exitCode) {
|
||||
Write-Host "Uninstall entry not found for product code: $productCode"
|
||||
Exit 0
|
||||
}
|
||||
|
||||
Write-Host "Uninstall exit code: $exitCode"
|
||||
# 0 = success, 3010 = success but reboot required, 1641 = reboot initiated
|
||||
if ($exitCode -eq 3010 -or $exitCode -eq 1641) { Exit 0 }
|
||||
Exit $exitCode
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "Microsoft Visual C++ 2013 Redistributable (x64)",
|
||||
"slug": "vc-redist-2013-x64/windows",
|
||||
"package_identifier": "Microsoft.VCRedist.2013.x64",
|
||||
"unique_identifier": "Microsoft Visual C++ 2013 Redistributable (x64)",
|
||||
"exists_query": "SELECT 1 FROM programs WHERE name LIKE 'Microsoft Visual C++ 2013 Redistributable (x64)%' AND publisher = 'Microsoft Corporation';",
|
||||
"installer_arch": "x64",
|
||||
"installer_type": "exe",
|
||||
"installer_scope": "machine",
|
||||
"install_script_path": "ee/maintained-apps/inputs/winget/scripts/vc_redist_x64_install.ps1",
|
||||
"uninstall_script_path": "ee/maintained-apps/inputs/winget/scripts/vc_redist_x64_uninstall.ps1",
|
||||
"default_categories": ["Developer tools"]
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "Microsoft Visual C++ 2015-2022 Redistributable (x64)",
|
||||
"slug": "vc-redist-x64/windows",
|
||||
"package_identifier": "Microsoft.VCRedist.2015+.x64",
|
||||
"unique_identifier": "Microsoft Visual C++ 2015-2022 Redistributable (x64)",
|
||||
"exists_query": "SELECT 1 FROM programs WHERE name LIKE 'Microsoft Visual C++ 2015-2022 Redistributable (x64)%' AND publisher = 'Microsoft Corporation';",
|
||||
"installer_arch": "x64",
|
||||
"installer_type": "exe",
|
||||
"installer_scope": "machine",
|
||||
"install_script_path": "ee/maintained-apps/inputs/winget/scripts/vc_redist_x64_install.ps1",
|
||||
"uninstall_script_path": "ee/maintained-apps/inputs/winget/scripts/vc_redist_x64_uninstall.ps1",
|
||||
"default_categories": ["Developer tools"]
|
||||
}
|
||||
@@ -2577,6 +2577,20 @@
|
||||
"unique_identifier": "com.utmapp.UTM",
|
||||
"description": "UTM is a virtual machines UI using QEMU."
|
||||
},
|
||||
{
|
||||
"name": "Microsoft Visual C++ 2013 Redistributable (x64)",
|
||||
"slug": "vc-redist-2013-x64/windows",
|
||||
"platform": "windows",
|
||||
"unique_identifier": "Microsoft Visual C++ 2013 Redistributable (x64)",
|
||||
"description": "Microsoft Visual C++ 2013 Redistributable (x64) installs the runtime components of the Visual C++ libraries required to run 64-bit applications built with Visual C++ 2013."
|
||||
},
|
||||
{
|
||||
"name": "Microsoft Visual C++ 2015-2022 Redistributable (x64)",
|
||||
"slug": "vc-redist-x64/windows",
|
||||
"platform": "windows",
|
||||
"unique_identifier": "Microsoft Visual C++ 2015-2022 Redistributable (x64)",
|
||||
"description": "Microsoft Visual C++ 2015-2022 Redistributable (x64) installs the runtime components of the Visual C++ libraries required to run 64-bit applications built with Visual C++ 2015, 2017, 2019, and 2022."
|
||||
},
|
||||
{
|
||||
"name": "VirtualBox",
|
||||
"slug": "virtualbox/darwin",
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "12.0.40664.0",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM programs WHERE name LIKE 'Microsoft Visual C++ 2013 Redistributable (x64)%' AND publisher = 'Microsoft Corporation';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name LIKE 'Microsoft Visual C++ 2013 Redistributable (x64)%' AND publisher = 'Microsoft Corporation' AND version_compare(version, '12.0.40664.0') < 0);"
|
||||
},
|
||||
"installer_url": "https://download.visualstudio.microsoft.com/download/pr/10912041/cee5d6bca2ddbcd039da727bf4acb48a/vcredist_x64.exe",
|
||||
"install_script_ref": "65654cc8",
|
||||
"uninstall_script_ref": "72bee0a9",
|
||||
"sha256": "a4bba7701e355ae29c403431f871a537897c363e215cafe706615e270984f17c",
|
||||
"default_categories": [
|
||||
"Developer tools"
|
||||
]
|
||||
}
|
||||
],
|
||||
"refs": {
|
||||
"65654cc8": "# Learn more about .exe install scripts:\n# http://fleetdm.com/learn-more-about/exe-install-scripts\n#\n# The Visual C++ Redistributable ships as a WiX \"burn\" bootstrapper (.exe). It\n# installs machine-wide and registers its own ARP entry. Silent switches come\n# from the winget installer manifest (burn bundles use /quiet /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",
|
||||
"72bee0a9": "# Uninstalls the Microsoft Visual C++ Redistributable WiX \"burn\" bundle.\n#\n# The redistributable installs as a burn bootstrapper that registers a *bundle*\n# ARP entry (keyed by the bundle ProductCode) alongside several MSI component\n# entries (\"...X64 Minimum Runtime...\", \"...Additional Runtime...\"). Only the\n# bundle entry removes the whole redistributable, and it uninstalls by running\n# its cached bootstrapper .exe with /uninstall -- never via msiexec. We target\n# the bundle by its ProductCode (injected by the ingester) and fall back to the\n# cached bootstrapper in the Package Cache.\n\n$productCode = '{042d26ef-3dbe-4c25-95d3-4c1b11b235a7}'\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"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "14.51.36231.0",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM programs WHERE name LIKE 'Microsoft Visual C++ 2015-2022 Redistributable (x64)%' AND publisher = 'Microsoft Corporation';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name LIKE 'Microsoft Visual C++ 2015-2022 Redistributable (x64)%' AND publisher = 'Microsoft Corporation' AND version_compare(version, '14.51.36231.0') < 0);"
|
||||
},
|
||||
"installer_url": "https://download.visualstudio.microsoft.com/download/pr/c1bd4f2c-3672-468e-8480-7ed419dbb641/90E48ADE404E4576D023ABFA374F323555F233982A8805EA9AC63DCA9491A16B/VC_redist.x64.exe",
|
||||
"install_script_ref": "65654cc8",
|
||||
"uninstall_script_ref": "5077ddcb",
|
||||
"sha256": "90e48ade404e4576d023abfa374f323555f233982a8805ea9ac63dca9491a16b",
|
||||
"default_categories": [
|
||||
"Developer tools"
|
||||
]
|
||||
}
|
||||
],
|
||||
"refs": {
|
||||
"5077ddcb": "# Uninstalls the Microsoft Visual C++ Redistributable WiX \"burn\" bundle.\n#\n# The redistributable installs as a burn bootstrapper that registers a *bundle*\n# ARP entry (keyed by the bundle ProductCode) alongside several MSI component\n# entries (\"...X64 Minimum Runtime...\", \"...Additional Runtime...\"). Only the\n# bundle entry removes the whole redistributable, and it uninstalls by running\n# its cached bootstrapper .exe with /uninstall -- never via msiexec. We target\n# the bundle by its ProductCode (injected by the ingester) and fall back to the\n# cached bootstrapper in the Package Cache.\n\n$productCode = '{c157798c-9519-4e56-98d9-f696f78f4a61}'\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",
|
||||
"65654cc8": "# Learn more about .exe install scripts:\n# http://fleetdm.com/learn-more-about/exe-install-scripts\n#\n# The Visual C++ Redistributable ships as a WiX \"burn\" bootstrapper (.exe). It\n# installs machine-wide and registers its own ARP entry. Silent switches come\n# from the winget installer manifest (burn bundles use /quiet /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"
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -268,6 +268,7 @@ import Transmit from "./Transmit";
|
||||
import Tunnelblick from "./Tunnelblick";
|
||||
import Twingate from "./Twingate";
|
||||
import Utm from "./Utm";
|
||||
import VcRedistX64 from "./VcRedistX64";
|
||||
import VirtualBox from "./VirtualBox";
|
||||
import VirtualBuddy from "./VirtualBuddy";
|
||||
import Viscosity from "./Viscosity";
|
||||
@@ -477,6 +478,7 @@ export const SOFTWARE_NAME_TO_ICON_MAP = {
|
||||
"microsoft outlook": MicrosoftOutlook,
|
||||
"microsoft powerpoint": MicrosoftPowerPoint,
|
||||
"microsoft teams": Teams,
|
||||
"microsoft visual c++": VcRedistX64,
|
||||
"microsoft visual studio code": VisualStudioCode,
|
||||
"microsoft word": Word,
|
||||
miro: Miro,
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 9.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 9.1 KiB |
Reference in New Issue
Block a user