ADR 0011 — Pre-Extracted MSIs, Not the InstallShield Self-Extractor

Status: Accepted (build-discovered, 2026-07-10). One of the deepest traps hit in the Windows golden-image build — see Build traps #4 for the symptom-table entry.

Context

The Windows golden-image pipeline (Windows golden image pipeline, stage 2 — Symphony install onto the windows-efi-installer-built base image) originally shelled out to IBM’s shipped Windows installer, symeval-7.3.2.0.exe, with InstallAnywhere-style silent flags (-i silent -DVAR=val) copied from the Linux .bin twin’s documented pattern.

This failed on roughly ten consecutive stage-2 attempts. Root-causing it turned up a chain of compounding problems, most of them upstream of Symphony itself:

  • symeval-7.3.2.0.exe is not an InstallAnywhere installer like its Linux counterpart — it is an InstallShield self-extracting bundle of native MSI packages. InstallAnywhere flags fall silently through to the full interactive GUI wizard, which then hangs forever waiting for input in an unattended pipeline (strings -n 6 on the binary found zero InstallAnywhere markers, only InstallShield.Setup).

  • symeval --extract <dir> is itself a real, non-headless 3-click InstallShield wizard (Welcome→Next, License→Accept, Complete→Finish) — confirmed only by live VNC screenshot, not by any log or exit code.

  • A previously undocumented Windows "Networks" shell flyout ("allow your PC to be discoverable") can sit on top of the License Agreement dialog and silently block headless BM_CLICK button automation — it is a titleless XAML ShellExperienceHost surface that EnumWindows/GetWindowText cannot see as a normal window, and NetworkLocation=Work in the unattend file does not suppress it.

  • Three successive automation watchdogs (fixed timeout, disk-growth heuristic, process-tree CPU heuristic) each falsely diagnosed these stalls as a slow/stuck extract and killed genuinely-fine-but-waiting-on-a-dialog runs, before a single screenshot settled the question in one look. The project recorded the general lesson: "when a guard has killed more healthy runs than it caught real failures, the guard is the bug."

  • Once extraction was forced through once, the real installed artifact names turned out to be egocore-4.0.0.0.msi and soamcore-7.3.2.0.msi — not egocore-7.3.2.0.msi as every script and doc had assumed. egocore is versioned against the EGO base release (ego_base 4.0 in the eval entitlement), not the Symphony product version; soamcore does track the product version as expected. Getting this wrong would 404 against a served path built from the wrong assumption.

Decision

Stop fighting the self-extractor inside the pipeline. Extract the two required MSIs (egocore-4.0.0.0.msi, soamcore-7.3.2.0.msi) exactly once, by hand, in a throwaway VM (manual VNC clicks accepted for this one-time step — total wall clock ~13 minutes including the clicks). Publish the extracted MSIs to installer-repo over a new WebDAV drop-in on the existing nginx server (windows/msi/). Rewrite install-symphony.ps1 to stop calling symeval.exe at all and instead just run msiexec /qn against the pre-served MSIs pulled from installer-repo.

This eliminates self-extraction, GUI-wizard automation, and all in-pipeline watchdog logic from the golden-image build permanently — msiexec /qn is genuinely silent and its exit code is trustworthy.

Consequences

Pros

  • Removes an entire class of non-determinism (InstallShield GUI automation, the invisible Networks flyout, watchdog false-positives) from the automated pipeline — stage 2 now runs deterministic, silent MSI installs with real, checkable exit codes.

  • The one-time extract is done once per Symphony version, not once per pipeline run — the ~10-failed-attempt cost was paid once, not on every image build.

  • Matches the general project lesson that fragile guards against a misunderstood failure mode should be replaced by fixing the actual failure mode, not tuned further.

Cons

  • Introduces a manual, human-in-the-loop step (the one-time MSI extract, with VNC clicks) per Symphony version upgrade — this is not part of the automated pipeline and must be re-run and re-published deliberately whenever IBM ships a new symeval/production installer build.

  • installer-repo must now serve MSIs over WebDAV in addition to whatever it already served — a new artifact type and endpoint to keep in sync with the version actually installed.

  • The extracted MSI filenames are not self-evidently correlated with the Symphony product version (egocore tracks the EGO base version, soamcore tracks the product version) — this mismatch must be re-verified, not assumed, on every future extract (e.g. via msitools), or the same wrong-filename class of bug recurs.