fix(installer): install the Visual C++ runtime before MySQL, and log the MSI
Some checks failed
CI / backend (push) Failing after 7s
CI / naming (push) Successful in 2s
CI / frontend (push) Successful in 9s
CI / migrations-mysql (push) Failing after 6s

Second failure from the Server 2019 test. The previous fix worked - msiexec went
from exit 1639 (ERROR_INVALID_COMMAND_LINE, which is why it printed its usage
dialog) to exit 1603 (ERROR_INSTALL_FAILURE), so the command line parses now and
the MSI itself is failing.

It failed in 1.1 seconds. An MSI that dies that fast has not begun installing;
it has failed a launch condition. MySQL 8.4 requires the Visual C++
redistributable and a bare Windows Server does not ship it - the same runtime
mysql.exe and mysqldump.exe import, which was visible when their DLL
dependencies were trimmed and went unnoticed.

Stage 0 now installs VC_redist.x64.exe from the bundle before touching MySQL,
skipping it when vcruntime140.dll is already present, and fails with a sentence
naming the requirement if the redistributable is absent from the bundle
altogether. vcredist\ is an optional locked payload.

msiexec also gets /l*v now. A bare 1603 names neither the failing action nor the
reason, and it is the most common MySQL install failure - diagnosing this one
took a launch-condition inference rather than a log. The MSI log lands beside
the installer's own in ProgramData, so the next failure is readable instead of
guessed at.
This commit is contained in:
cproudlock
2026-08-04 12:17:36 -04:00
parent 8d0afc40d3
commit 263ae8e3b4
7 changed files with 218 additions and 172 deletions

View File

@@ -677,9 +677,42 @@ Skip stage 0 and point the installer at the existing server with -DbHost.
Write-Log "could not start msiserver: $($_.Exception.Message)" 'WARN'
}
}
# The Visual C++ runtime, BEFORE MySQL. MySQL's MSI carries a launch
# condition requiring it, and a bare Windows Server does not ship it -
# so on a fresh box the MSI aborts in about a second with the generic
# exit 1603 and no indication of what was missing. That is what a real
# Server 2019 install did.
$vcMarker = Join-Path $env:windir 'system32\vcruntime140.dll'
if (Test-Path $vcMarker) {
Write-Log 'Visual C++ runtime already present' 'OK'
} else {
$vc = Get-ChildItem (Join-Path $BundleRoot 'vcredist') -Filter '*.exe' -ErrorAction SilentlyContinue |
Select-Object -First 1
if (-not $vc) {
Fail 'the Visual C++ runtime is missing and no redistributable is in the bundle' @'
MySQL will not install without it - its MSI fails with a bare exit 1603.
Add vcredist\VC_redist.x64.exe to the bundle and rebuild, or install the
Microsoft Visual C++ 2015-2022 Redistributable (x64) on this server by hand.
'@
}
Write-Log "installing $($vc.Name) (MySQL requires it)"
if (-not $WhatIfOnly) {
Invoke-Native $vc.FullName @('/install','/quiet','/norestart') `
'Visual C++ runtime' -TimeoutSec 600
Write-Log 'Visual C++ runtime installed' 'OK'
}
}
# Quiet MSI. INSTALLDIR must have no trailing backslash or the MSI mis-parses it.
Write-Log "installing $($msi.Name) (125MB, takes a minute)"
# /l*v: without the MSI's own log, exit 1603 says only "something went
# wrong" - it names neither the action nor the reason, and it is the most
# common MySQL failure code. Costs nothing and turns the next failure
# into something readable.
$msiLog = Join-Path $script:LogDir ('mysql-msi-{0}.log' -f (Get-Date -Format 'yyyyMMdd-HHmmss'))
Write-Log "MSI log: $msiLog"
Invoke-Native 'msiexec.exe' @('/i', $msi.FullName, '/quiet', '/norestart',
'/l*v', $msiLog,
"INSTALLDIR=$MysqlRoot") 'MySQL MSI' -TimeoutSec 900
}
# An installer exit code of 0 does NOT mean it did what you asked - the Python