A PowerShell-based toolkit for managing Microsoft Visual C++ Redistributable runtimes across Windows environments at scale. Forked from abbodi1406/vcredist (a batch/.NET AIO repack), rewritten in PowerShell to address reliability issues encountered when deploying across ~400 servers.
The upstream project provides an all-in-one repack of the latest VC++ redistributables, but its batch-based installer proved too fragile for large managed environments (SCCM/MECM). Common issues included unreliable detection, incomplete uninstalls of WiX-bundled packages, and poor handling of edge cases like Restart Manager interference. This rewrite solves those problems with structured compliance checking, intelligent WiX bundle detection, and robust MSI exit code handling.
├── Update-VisualCppRedists.ps1 # Main orchestrator — runs compliance checks, uninstalls, and installs
├── Get-VisualCppRedistInstallers.ps1 # Downloads the latest AIO repack from abbodi1406/vcredist via GitHub API and extracts the MSI installers using portable 7-Zip
├── InstallerRegistration.ps1 # Microsoft-derived MSI registration utilities (GUID compression, product enumeration, registry backup/restore, force-uninstall via registry scrub) — dot-sourced by the main script when -AllowForceUninstall is used
├── Update-VCppManifest.ps1 # Updates VisualCppRedistsManifest.json with latest expected versions/product codes
├── VisualCppRedistsManifest.json # Declarative product catalog — product codes, DLL baselines, installer paths, regex filters, and per-product flags
└── mecm/ # MECM/SCCM deployment artifacts
Every product in the manifest is validated against three independent checks before any action is taken. All three must pass for a product to be considered compliant.
1. DLL Version Check (Test-VcRedistDllCompliance) — Resolves wildcarded DLL paths (including WinSxS for older runtimes), reads FileVersionRaw to avoid string-parsing issues with stamps like 11.00.51106.1 built by: Q11REL, and compares the highest discovered version against the manifest baseline. If no DLL is found on disk, this check passes — MSI presence is validated separately.
2. WiX/Burn Bundle Detection (Test-IsWixBundle) — Any redistributable installed via a WiX Burn bundle is treated as non-compliant by default (overridable with -SkipUpToDateWiXBundle). Detection uses multiple signals: Bundle* registry properties, .exe uninstallers pointing to Package Cache, state.rsm files, and dependency mappings under HKLM:\SOFTWARE\Classes\Installer\Dependencies.
3. Registered Installations — Compares expected MSI ProductCodes from the manifest against what's actually registered in the x86/x64 uninstall hives. A product is compliant only when there are no missing entries, no unexpected entries, no WiX-installed products, and the expected count matches exactly. Special handling exists for VC++ 2005/2008, which may deploy DLLs into WinSxS without MSI registration — when doNotReinstallIfOrphanedDll is set and the DLL version check passes, these are considered compliant.
Each compliance result includes a Note field with a plain-English explanation, making output self-explanatory and auditable.
WiX Burn bundles typically register in the 32-bit uninstall hive regardless of the actual payload architecture. A multi-layer fallback determines the true architecture:
- All dependent MSI installs share one architecture → trust that
- 32-bit OS → always x86
- Uninstaller path contains
x64orx86→ infer from path - DisplayName contains architecture hints (
x64,64-bit, etc.) → infer from name
Debug runtimes are explicitly excluded via -notmatch '(?i)\b(Debug)\b' in the Get-Installs function. Debug runtimes are developer-only and produce false positives in compliance checks — they should never be remediated in production.
When a product fails compliance, the script uninstalls and reinstalls in order:
Uninstall rules:
| Scenario | Action |
|---|---|
| WiX bundle detected | Uninstall via bundle EXE (/uninstall /quiet /norestart) |
| MSI installed by WiX | Handled by bundle uninstall |
| Standalone MSI | Uninstall via msiexec /X |
Install: Each MSI from the manifest's installers array is installed via msiexec /i with /qn /norestart.
Key implementation details:
.Handleis cached before reading.ExitCode— a PS 5.1 workaround for reliable exit code retrieval- MSI exit codes handled:
0(success),3010(reboot required),1605(already uninstalled),1612(triggers force-repair → uninstall → reinstall cycle),1618/0x80070652(install in progress — retries after 5 minutes) - When
-AllowForceUninstallis set, failed uninstalls fall back toInstallerRegistration.ps1which scrubs the MSI registration from the registry (with backup toC:\MATS\) using methods derived from Microsoft's Install/Uninstall Troubleshooter (MicrosoftProgram_Install_and_Uninstall.meta.diagcab)
The Windows Restart Manager can kill processes (including CcmExec) mid-operation, producing exit codes like 1601 or 0xC000013A and terminating the script. All MSI operations use MSIRESTARTMANAGERCONTROL=Disable and /norestart to prevent forced process termination, deferring file-lock resolution to a controlled reboot — critical for managed environments like SCCM/MECM.
# 1. Download and extract the installer MSIs from the upstream repack
.\Get-VisualCppRedistInstallers.ps1
# 2. Run the update (requires elevation)
.\Update-VisualCppRedists.ps1| Parameter | Description |
|---|---|
-WhatIf |
Dry-run mode — prints all Start-Process commands without executing them |
-Verbose |
Outputs all compliance check details, not just failures |
-AllowForceUninstall |
On failed uninstall, scrubs MSI registration from registry using Microsoft's troubleshooter methods (backs up to C:\MATS\) |
-SkipUpToDateWiXBundle |
Treats WiX bundles as compliant if the DLL version check passes, only reinstalling when version check fails |
The mecm/ directory contains artifacts for deploying via Microsoft Endpoint Configuration Manager. When run non-interactively (e.g., deployed via SCCM), the script passes exit codes back to the parent process — returning 3010 if any operation required a reboot.
The manifest covers VC++ 2005 through 2022 (both x86 and x64), plus Visual Studio 2010 Tools for Office Runtime. Each entry defines product codes, DLL paths (including WinSxS patterns for older runtimes), version baselines, regex filters for DisplayName matching, and installer paths relative to the extracted repack.
- Compliance-first: Check before acting; produce auditable, structured output
- Declarative catalog: The manifest defines expected state; the script enforces it
- Flat control flow: Early
continueover deep nesting - Functions only when justified: Reuse exists or complexity is meaningfully reduced
- Safe for managed environments: No process kills, no surprise reboots,
MSIRESTARTMANAGERCONTROL=Disableeverywhere
- Source installers directly from Microsoft rather than relying on the upstream AIO repack (the repacks are more space-efficient, but direct sourcing removes a dependency)
Forked from abbodi1406/vcredist — an AIO repack of the latest Microsoft Visual C++ Redistributable runtimes.