Architecture
The big picture: three projects, a dual-mode executable, the two-model bridge, and why the install engine lives in BeepDM.
Three projects, one rule
The solution is split by a deliberate boundary — authoring/build/packaging lives in Beep.Installer; the runtime install engine lives in BeepDM (whose own scope doc lists an installer service but excludes packaging and code-signing).
| Project | Target | Responsibility |
|---|---|---|
Beep.Installer.Core | net10.0 (no UI) | Authoring model, .bsetup serializer, source scanner, BuildPipeline, payload packaging, packaging (ClickOnce/MSIX/signing), the runtime context projector, and FeedPublisher. |
Beep.Installer | net10.0-windows (WinForms) | A thin shell: the Package Builder UI, the runtime wizard, wizard pages, the install step graph (InstallWizardGraph), i18n, and Program.cs mode dispatch. |
Beep.Installer.Tests | net10.0-windows | xUnit + FluentAssertions. |
Two more libraries and a server layer post-install features on top: Beep.Installer.Extensions.Winform / .WPF (drop-in update UI) and Beep.Installer.UpdateServer (optional hosting).
One executable, two modes
Beep.Installer.exe is both the generator and the Track-A runtime. Program.Dispatch picks a mode from the CLI args and whether an installer script exists beside/inside the exe:
- A shipped installer carries
script.bsetup(on disk next to the exe, or embedded as a PE resource) → it runs as the installer (wizard or silent). - CLI verbs (
/BUILD,/PUBLISH,/S,/UNINSTALL,/CHECKUPDATE, …) select the corresponding headless mode. - Otherwise the Package Builder UI opens.
The two-model bridge
The authoring model (Beep.Installer.Models.InstallProject) is not what the install steps consume — they read BeepDM's InstallConfig from a SetupContext. The Runtime/ layer performs that projection and populates every context key the step graph reads:
InstallProject (.bsetup authoring)
│ InstallConfigProjector.ToInstallConfig
▼
InstallConfig + InstallContextBuilder.ForInstall
│ (InstallPath, LaunchPath, PerUser, RollbackManager, SideBySide, …)
▼
SetupContext → BeepDM install steps (FileCopyStep, RegistryWriteStep, …)
When adding a step that needs new config, wire it through the projector/builder — never reach into the authoring model from a step.
The install engine is in BeepDM
The actual install steps — PrerequisiteCheckStep, FileCopyStep, ShortcutCreateStep, RegistryWriteStep, VerifyInstallStep, UpgradeStep, JunctionCreateStep, UninstallStep — live in BeepDM under TheTechIdea.Beep.Installer.Steps / TheTechIdea.Beep.SetUp. Beep.Installer only composes and drives them via Hosting/InstallWizardGraph, which is the single place those steps are ordered into a wizard for install, repair, uninstall and self-test.
The app self-update domain (TheTechIdea.Beep.Updates) also lives in BeepDM (decision D12), so any Beep-based app gets self-update by registering one service — independent of how it was deployed.
Cross-repo build note
Beep.Installer references sibling source repos by relative path (..\..\BeepDM\, ..\..\Beep.Winform\). DataManagementModels is referenced directly (not just transitively) with NoWarn NU1605 — the control libraries carry a same-versioned NuGet DataManagementModels and NuGet resolves nearest-to-root, so the direct reference is what makes the source win. The extension libraries and the server follow the same pattern.