Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/Skidbladnir

.nornir/msi-guide.md

msi — guide

Class: guide · audience: a techie packaging a Windows product. The what is in msi-design.md.

Describe the Windows product

use skidbladnir::msi::{WindowsComponentSpec, WindowsServiceSpec, ServiceStart, WixFile};

let spec = WindowsComponentSpec {
    name: "holger".into(),
    display_name: "Holger".into(),
    version: "0.1.5".into(),
    upgrade_code: "…stable-upgrade-code…".into(),
    install_dir: r"C:\Program Files\Nordisk\Holger".into(),
    service: WindowsServiceSpec {
        account: "LocalSystem".into(),
        start: ServiceStart::Auto,
        delayed: true,
        env_block: vec![("HOLGER_DATA".into(), r"C:\ProgramData\Holger".into())],
    },
    files: vec![WixFile { source: "holger.exe".into(), id: "holgerexe".into() }],
};

Render the WiX source (no tooling needed)

let wxs = skidbladnir::msi::render_wxs(&spec);   // pure — a real Product.wxs string
// each file carries a stable component GUID; the service block is registered

Mint a stable component GUID

let g = skidbladnir::msi::component_guid("holger-main-exe");   // same id → same GUID, every build

Stable GUIDs are what make MSI upgrades (not side-by-side installs) work — never randomize them.

Build the MSI (needs podman + the WiX-in-Wine image)

use skidbladnir::msi::WixBuilder;

let builder = WixBuilder::new("registry/nordisk/wix-wine:4");
if builder.podman_available() {
    builder.build(&spec, std::path::Path::new("holger.msi"))?;
} else {
    // build() would bail with a clear message and leave the rendered WXS staged for inspection
}

Gotchas