19 KiB
Dragon-ISO Installer Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Rebrand the WiX v5 MSI installer from TeamsISO to Dragon-ISO, producing Dragon-ISO-Setup-1.0.0.0.msi for end-user download.
Architecture: Rename the .wixproj file, rewrite Package.wxs with Dragon-ISO branding and a simple WixUI_Minimal UI (no directory picker), and fix a bug in release.yml where the signing step references the wrong executable filename.
Tech Stack: WiX Toolset v5, MSBuild, PowerShell; no unit tests (installer files are build-verified by dotnet build)
File Map
| File | Action | Responsibility |
|---|---|---|
installer/TeamsISO.Installer.wixproj |
Rename + rewrite | MSBuild project — output name, publish dir, asset dir |
installer/Dragon-ISO.Installer.wixproj |
Created by rename | Same as above, Dragon-ISO branded |
installer/Package.wxs |
Rewrite | WiX source — all installer logic, shortcuts, metadata |
.forgejo/workflows/release.yml |
Fix line 119 | Fix Dragon-ISO.exe → DragonISO.exe (exe filename matches AssemblyName) |
Important:
Dragon-ISO.App.csprojhas<AssemblyName>DragonISO</AssemblyName>(no hyphen). The published executable is thereforeDragonISO.exe, notDragon-ISO.exe. All shortcut targets and signing steps must useDragonISO.exe.
Task 1: Rename the .wixproj file
Files:
-
Rename:
installer/TeamsISO.Installer.wixproj→installer/Dragon-ISO.Installer.wixproj -
Step 1: Rename the file using git mv
cd C:\Users\zacga\source\repos\Dragon-ISO
git mv installer/TeamsISO.Installer.wixproj installer/Dragon-ISO.Installer.wixproj
- Step 2: Verify the rename
Get-ChildItem installer/
Expected: Dragon-ISO.Installer.wixproj and Package.wxs (no TeamsISO.Installer.wixproj)
Task 2: Rewrite Dragon-ISO.Installer.wixproj
Files:
-
Modify:
installer/Dragon-ISO.Installer.wixproj -
Step 1: Replace the file content entirely
Write the following to installer/Dragon-ISO.Installer.wixproj:
<Project Sdk="WixToolset.Sdk/5.0.2">
<PropertyGroup>
<OutputType>Package</OutputType>
<OutputName>Dragon-ISO-Setup-$(Version)</OutputName>
<!-- 64-bit MSI; suppresses ICE80 on components in Program Files (x64). -->
<Platform>x64</Platform>
<InstallerPlatform>x64</InstallerPlatform>
<!--
Built artifact location. The installer expects a published build of
Dragon-ISO.App rooted here. CI / local script:
dotnet publish src/Dragon-ISO.App/Dragon-ISO.App.csproj
-c Release -r win-x64 --self-contained false
-o $(SolutionDir)publish/Dragon-ISO
-->
<PublishDir>$(MSBuildThisFileDirectory)..\publish\Dragon-ISO\</PublishDir>
<!-- Pass MSBuild values into WiX preprocessor. -->
<DefineConstants>PublishDir=$(PublishDir);AssetsDir=$(MSBuildThisFileDirectory)..\src\Dragon-ISO.App\Assets\</DefineConstants>
<!-- Code-signing hook (set externally for release builds; left empty for dev). -->
<SignOutput Condition=" '$(SignOutput)' == '' ">false</SignOutput>
</PropertyGroup>
<!--
Reference the WiX UI extension so the MSI shows a friendly progress UI
instead of the silent default.
-->
<ItemGroup>
<PackageReference Include="WixToolset.UI.wixext" Version="5.0.2" />
</ItemGroup>
</Project>
- Step 2: Verify the file reads back correctly
Get-Content installer/Dragon-ISO.Installer.wixproj | Select-String "OutputName|PublishDir|AssetsDir"
Expected output (3 lines):
<OutputName>Dragon-ISO-Setup-$(Version)</OutputName>
<PublishDir>$(MSBuildThisFileDirectory)..\publish\Dragon-ISO\</PublishDir>
<DefineConstants>PublishDir=$(PublishDir);AssetsDir=$(MSBuildThisFileDirectory)..\src\Dragon-ISO.App\Assets\</DefineConstants>
Task 3: Rewrite Package.wxs with Dragon-ISO branding
Files:
- Modify:
installer/Package.wxs
Changes from the original TeamsISO version:
-
Package Name: "TeamsISO" → "Dragon-ISO"
-
SummaryInformation description and keywords updated
-
MajorUpgrade error message updated
-
Feature Title: "TeamsISO" → "Dragon-ISO"
-
UI switched from
WixUI_InstallDir(shows dir picker) →WixUI_Minimal(Welcome → Install → Finish) -
WIXUI_INSTALLDIRproperty removed (not used by WixUI_Minimal) -
ARPHELPLINK URL: teamsiso → dragon-iso
-
ARPCOMMENTS: "TeamsISO" → "Dragon-ISO"
-
Icon Id: "TeamsISOIcon" → "DragonISOIcon"
-
Icon SourceFile:
teamsiso.ico→Dragon-ISO.ico -
ARPPRODUCTICON value: "TeamsISOIcon" → "DragonISOIcon"
-
Added .NET 8 Desktop Runtime detection property
-
Install directory Name: "TeamsISO" → "Dragon-ISO"
-
Start Menu shortcut Id/Name/Target/Icon updated
-
Desktop shortcut Id/Name/Target/Icon updated
-
All registry keys:
Software\Wild Dragon\TeamsISO→Software\Wild Dragon\Dragon-ISO -
Shortcut targets:
TeamsISO.exe→DragonISO.exe(matches AssemblyName, no hyphen) -
Step 1: Replace Package.wxs entirely with Dragon-ISO branded content
Write the following to installer/Package.wxs:
<?xml version="1.0" encoding="UTF-8"?>
<!--
Dragon-ISO — MSI installer (WiX v5)
Produces: Dragon-ISO-Setup-<Version>.msi (per-machine install).
Build:
dotnet publish src/Dragon-ISO.App/Dragon-ISO.App.csproj -c Release -r win-x64 --self-contained false -o publish/Dragon-ISO
dotnet build installer/Dragon-ISO.Installer.wixproj -c Release
Runtime expectations:
- .NET 8 Desktop runtime present on target (framework-dependent build)
- NDI 6 Runtime present — checked in NdiRuntimeDirV6Search; absence WARNS
but does not block install (operators can install NDI after the app)
Exe filename note:
Dragon-ISO.App.csproj sets AssemblyName=DragonISO (no hyphen — CLR
assembly names cannot contain hyphens). The published executable is
therefore DragonISO.exe. Shortcut targets reference DragonISO.exe.
-->
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
xmlns:ui="http://wixtoolset.org/schemas/v4/wxs/ui">
<Package Name="Dragon-ISO"
Manufacturer="Wild Dragon LLC"
Version="1.0.0.0"
UpgradeCode="9F4A8B2C-1D3E-4A5B-9C6D-8E7F0A1B2C3D"
Scope="perMachine"
Compressed="yes"
InstallerVersion="500">
<!--
SummaryInformation fields surface in File Explorer's "Details" tab and
in the Windows Installer "About" dialog. Description and Keywords are
what users see if they right-click the MSI before installing; Comments
is the longer copy that appears alongside the version in some
installer dialogs.
-->
<SummaryInformation
Description="Dragon-ISO — per-participant NDI ISO controller for Microsoft Teams. Splits each Teams participant into a normalized NDI source for vMix / OBS / Ross / hardware switchers."
Manufacturer="Wild Dragon LLC"
Keywords="Dragon-ISO, NDI, Microsoft Teams, ISO recording, broadcast, live production, vMix, OBS, switcher, Wild Dragon" />
<!--
MajorUpgrade: a newer install replaces an older one in-place. We
disallow downgrades because the engine config schema only carries a
forward-migration path; downgrading would leave operators with a
config the older binary doesn't understand.
-->
<MajorUpgrade DowngradeErrorMessage="A newer version of Dragon-ISO is already installed. Uninstall it before installing this older version."
Schedule="afterInstallInitialize" />
<!--
Single MSI feature; users see only the install/uninstall screens.
-->
<Feature Id="Main" Title="Dragon-ISO" Level="1">
<ComponentGroupRef Id="ApplicationFiles" />
<ComponentGroupRef Id="Shortcuts" />
<ComponentGroupRef Id="DesktopShortcut" />
<ComponentGroupRef Id="ArpEntry" />
</Feature>
<!--
Minimal install UI: Welcome/License → Progress → Finish.
No directory picker — installs to Program Files\Wild Dragon\Dragon-ISO.
-->
<ui:WixUI Id="WixUI_Minimal" />
<!--
Add/Remove Programs metadata. ARPHELPLINK is the "Help" link; ARPURLINFOABOUT
is the manufacturer/about link; ARPCONTACT is the support contact shown
when the user clicks "Support information" from the ARP entry. ARPCOMMENTS
is the long description displayed in some Settings → Apps surfaces.
-->
<Property Id="ARPHELPLINK" Value="https://forge.wilddragon.net/zgaetano/dragon-iso" />
<Property Id="ARPURLINFOABOUT" Value="https://wilddragon.net" />
<Property Id="ARPCONTACT" Value="Wild Dragon LLC — support@wilddragon.net" />
<Property Id="ARPCOMMENTS" Value="Dragon-ISO turns Microsoft Teams' raw NDI broadcast into clean, normalized, per-participant NDI sources for ingestion by a live-production switcher (vMix, OBS, Ross, hardware capture). Each participant gets an individually-addressable source with configurable framerate, resolution, aspect mode, and audio routing." />
<!-- ARPNOMODIFY is set by WixUI_Minimal; don't redeclare. -->
<Property Id="ARPNOREPAIR" Value="1" />
<!--
ARP icon — references the same .ico the WPF host uses. WiX requires the
icon resource to live next to the wxs OR be reachable at build time;
we point at the source copy under src/Dragon-ISO.App/Assets so the icon
embedded in the MSI matches the icon in the running exe.
-->
<Icon Id="DragonISOIcon" SourceFile="$(var.AssetsDir)Dragon-ISO.ico" />
<Property Id="ARPPRODUCTICON" Value="DragonISOIcon" />
<!--
.NET 8 Desktop Runtime detection. The .NET apphost will surface a
"framework not found" dialog naturally if the runtime is absent;
this property is available for future conditional logic.
VBScript-based install-time dialogs are deprecated in WiX v5 / Windows;
rewriting in C++ is overkill for a soft warning on a soft dependency.
-->
<Property Id="DOTNET8DESKTOPRUNTIME" Value="0">
<RegistrySearch Id="DotNet8DesktopRuntimeSearch"
Root="HKLM"
Key="SOFTWARE\dotnet\Setup\InstalledVersions\x64\sharedfx\Microsoft.WindowsDesktop.App"
Name="8.0.0"
Type="raw" />
</Property>
<!--
NDI Runtime detection. We check for NDI_RUNTIME_DIR_V6 in the system
environment block. Missing → warn during install, don't block. The
engine surfaces a clear MessageBox with an install-NDI link at first
launch if the runtime really isn't there.
-->
<Property Id="NDIRUNTIMEDIR" Value="0">
<RegistrySearch Id="NdiRuntimeDirV6Search"
Root="HKLM"
Key="SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
Name="NDI_RUNTIME_DIR_V6"
Type="raw" />
</Property>
<!--
NDI runtime detection is surfaced at first app launch (App.xaml.cs pops a
MessageBox with an install link). We deliberately don't block install on
a missing runtime so admins can stage the app before NDI is rolled out.
VBScript-based install-time prompts are deprecated in WiX v5 / Windows
and rewriting in C++ is overkill for a soft warning.
-->
<!--
Install layout under Program Files\Wild Dragon\Dragon-ISO.
-->
<StandardDirectory Id="ProgramFiles64Folder">
<Directory Id="ManufacturerFolder" Name="Wild Dragon">
<Directory Id="INSTALLFOLDER" Name="Dragon-ISO" />
</Directory>
</StandardDirectory>
<StandardDirectory Id="ProgramMenuFolder">
<Directory Id="WildDragonStartMenuFolder" Name="Wild Dragon" />
</StandardDirectory>
<!--
Files: harvested from the publish output dir at build time.
WiX v5 understands <Files Include="..."> with glob patterns and
synthesizes one Component per file with stable GUIDs.
-->
<ComponentGroup Id="ApplicationFiles" Directory="INSTALLFOLDER">
<Files Include="$(var.PublishDir)**" />
</ComponentGroup>
<!--
Start Menu and Desktop shortcuts — direct .exe targets.
Don't wrap the Target in runas.exe /trustlevel:0x20000 (or anything
else that demotes the spawned process). The SAFER-restricted token
breaks .NET 8 WPF apphost startup: the process appears alive with
a window, but no managed code past BAML parse executes. Verified
empirically 2026-05-16 — letting Dragon-ISO inherit the launching
token (medium or high integrity, doesn't matter) is the correct
behavior. NDI discovery works fine at either integrity level.
Exe filename: AssemblyName=DragonISO (no hyphen), so target is
DragonISO.exe not Dragon-ISO.exe.
-->
<ComponentGroup Id="Shortcuts" Directory="WildDragonStartMenuFolder">
<Component Id="StartMenuShortcut" Guid="*">
<Shortcut Id="StartMenuDragonISO"
Name="Dragon-ISO"
Description="Per-Participant NDI ISO Controller for Microsoft Teams"
Target="[INSTALLFOLDER]DragonISO.exe"
WorkingDirectory="INSTALLFOLDER"
Icon="DragonISOIcon" />
<!-- Required by ICE64: Start Menu folder must be cleaned on uninstall. -->
<RemoveFolder Id="RemoveWildDragonStartMenuFolder"
Directory="WildDragonStartMenuFolder"
On="uninstall" />
<RegistryValue Root="HKCU"
Key="Software\Wild Dragon\Dragon-ISO"
Name="StartMenuShortcut"
Type="integer"
Value="1"
KeyPath="yes" />
</Component>
</ComponentGroup>
<StandardDirectory Id="DesktopFolder" />
<ComponentGroup Id="DesktopShortcut" Directory="DesktopFolder">
<Component Id="DesktopShortcutComponent" Guid="*">
<Shortcut Id="DesktopDragonISO"
Name="Dragon-ISO"
Description="Per-Participant NDI ISO Controller for Microsoft Teams"
Target="[INSTALLFOLDER]DragonISO.exe"
WorkingDirectory="INSTALLFOLDER"
Icon="DragonISOIcon" />
<RegistryValue Root="HKCU"
Key="Software\Wild Dragon\Dragon-ISO"
Name="DesktopShortcut"
Type="integer"
Value="1"
KeyPath="yes" />
</Component>
</ComponentGroup>
<!--
ARP icon registry entry. Optional — the MSI auto-fills most ARP
fields from the Package element. We only need to store the install
path for diagnostic / uninstall tooling.
-->
<ComponentGroup Id="ArpEntry" Directory="INSTALLFOLDER">
<Component Id="ArpIconRegistry" Guid="*">
<RegistryValue Root="HKLM"
Key="Software\Wild Dragon\Dragon-ISO"
Name="InstallPath"
Type="string"
Value="[INSTALLFOLDER]"
KeyPath="yes" />
</Component>
</ComponentGroup>
</Package>
</Wix>
- Step 2: Verify no "TeamsISO" strings remain in Package.wxs
Select-String -Path installer/Package.wxs -Pattern "TeamsISO"
Expected: no output (zero matches)
Task 4: Fix release.yml — wrong exe filename in signing step
Files:
- Modify:
.forgejo/workflows/release.ymlline 119
The signing step references publish/Dragon-ISO/Dragon-ISO.exe but the app's AssemblyName is DragonISO, so the published exe is DragonISO.exe. Fix it.
- Step 1: Edit release.yml to fix the exe path
In .forgejo/workflows/release.yml, find and replace:
Old (line 119):
'publish/Dragon-ISO/Dragon-ISO.exe'
New:
'publish/Dragon-ISO/DragonISO.exe'
- Step 2: Verify the fix
Select-String -Path .forgejo/workflows/release.yml -Pattern "Dragon-ISO\.exe|DragonISO\.exe"
Expected output:
.forgejo/workflows/release.yml:119: 'publish/Dragon-ISO/DragonISO.exe'
(One match, using DragonISO.exe with no hyphen)
Task 5: Check WiX workload and verify build
Files: None (verification only)
- Step 1: Check if WiX workload is installed
dotnet workload list
Expected: output includes wix in the list. If not installed, run:
dotnet workload install wix
- Step 2: Publish the app to the expected location
cd C:\Users\zacga\source\repos\Dragon-ISO
dotnet publish src/Dragon-ISO.App/Dragon-ISO.App.csproj `
-c Release -r win-x64 --self-contained false `
-o publish/Dragon-ISO
Expected: ends with Build succeeded. and creates publish/Dragon-ISO/DragonISO.exe
- Step 3: Verify the exe filename in the publish output
Get-ChildItem publish/Dragon-ISO/ -Filter "*.exe"
Expected: one file named DragonISO.exe (confirms shortcut targets are correct)
- Step 4: Build the MSI
dotnet build installer/Dragon-ISO.Installer.wixproj -c Release /p:Version=1.0.0.0
Expected: ends with Build succeeded. — no errors, no warnings.
- Step 5: Verify the MSI was produced with the correct name
Get-ChildItem installer/bin -Recurse -Filter "*.msi"
Expected: one file named Dragon-ISO-Setup-1.0.0.0.msi
Task 6: Commit all changes
- Step 1: Stage the changed files
cd C:\Users\zacga\source\repos\Dragon-ISO
git add installer/Dragon-ISO.Installer.wixproj
git add installer/Package.wxs
git add .forgejo/workflows/release.yml
- Step 2: Verify nothing unexpected is staged
git status
Expected staged files:
installer/Dragon-ISO.Installer.wixproj(renamed from TeamsISO.Installer.wixproj)installer/Package.wxs(modified).forgejo/workflows/release.yml(modified)
No other files should be staged.
- Step 3: Commit
git commit -m "$(cat <<'EOF'
rebrand installer from TeamsISO to Dragon-ISO
- Rename TeamsISO.Installer.wixproj → Dragon-ISO.Installer.wixproj
- Update Package.wxs: product name, shortcuts, registry keys, ARP
metadata, install directory, and icon all updated to Dragon-ISO
- Switch UI from WixUI_InstallDir to WixUI_Minimal (no dir picker)
- Add .NET 8 Desktop Runtime detection property
- Fix release.yml: signing step referenced Dragon-ISO.exe but
AssemblyName=DragonISO so exe is DragonISO.exe (no hyphen)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
EOF
)"
Testing Checklist (manual verification after install)
Once the MSI is built, install it on a test machine and verify:
Dragon-ISO-Setup-1.0.0.0.msiinstalls without errors- App installs to
C:\Program Files\Wild Dragon\Dragon-ISO\ DragonISO.exeis present in the install folder- Start Menu shows
Wild Dragon → Dragon-ISOshortcut with correct icon - Desktop shows
Dragon-ISOshortcut with correct icon - Both shortcuts launch the app successfully
- Add/Remove Programs shows:
- Name: Dragon-ISO
- Publisher: Wild Dragon LLC
- Version: 1.0.0.0
- Help link:
https://forge.wilddragon.net/zgaetano/dragon-iso
- Uninstall removes all files, shortcuts, and registry entries
%APPDATA%\Dragon-ISO\(user config) is NOT removed on uninstall