teamsiso/installer/Package.wxs

199 lines
8.9 KiB
Text
Raw Normal View History

<?xml version="1.0" encoding="UTF-8"?>
<!--
TeamsISO — MSI installer (WiX v5)
Produces: TeamsISO-Setup-<Version>.msi (per-machine install).
Build:
dotnet publish src/TeamsISO.App/TeamsISO.App.csproj -c Release -r win-x64 (no self contained) -o publish/TeamsISO
dotnet build installer/TeamsISO.Installer.wixproj -c Release
Runtime expectations:
- .NET 8 Desktop runtime present on target (framework-dependent build)
- NDI 6 Runtime present — checked in CheckNdiRuntime; absence WARNS
but does not block install (operators can install NDI after the app)
-->
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
xmlns:ui="http://wixtoolset.org/schemas/v4/wxs/ui">
<Package Name="TeamsISO"
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="TeamsISO — 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="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 TeamsISO 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="TeamsISO" Level="1">
<ComponentGroupRef Id="ApplicationFiles" />
<ComponentGroupRef Id="Shortcuts" />
fix: cold-start discovery + installer shortcuts + single-instance hardening Three independent fixes bundled because all were chasing the same operator report: 'I just installed, launched from the shortcut, no participants.' 1) NdiDiscoveryService: poll immediately, then ramp from 200ms to the configured interval over the first 3 seconds. PeriodicTimer.WaitForNext- TickAsync waits the full interval before its first tick, so for a 500ms discovery interval the operator stared at 'no ndi sources yet' for half a second on every cold start. Force-poll up front (catches the runtime cache), then run a fast inner loop for ~3s while mDNS replies trickle in. Both loops share a try/finally so the NDI finder is always disposed. 2) MainViewModel.IsDiscovering: new boolean, true for 8s after engine start AS LONG AS no participants have arrived. MainWindow.xaml swaps the empty-state copy on this binding: IsDiscovering=true -> 'scanning for ndi sources...' (cyan dot) IsDiscovering=false -> 'no ndi sources visible -- is teams in a meeting?' + Refresh CTA The old copy ('no ndi sources yet -- open teams and start a meeting') was being shown immediately at launch even when discovery just hadn't run yet, making the app look broken. 3) App.xaml.cs: single-instance mutex moved from Local\ to Global\. On admin-user boxes with UAC disabled, launches from different parents (elevated File Explorer, non-elevated shell, etc.) can land in slightly different security contexts and a Local\ name can be invisible to the sibling. Global\ namespace closes that hole — both processes see the same mutex regardless of integrity. Belt-and-braces against future dual-instance file/port contention. 4) installer/Package.wxs: add a Desktop shortcut component (per-machine feature, HKCU keypath per ICE38/ICE43). Operators who can't find the Start Menu entry get the Desktop icon. Both shortcuts target the installed exe, NOT a stale path under publish/.
2026-05-16 11:23:19 -04:00
<ComponentGroupRef Id="DesktopShortcut" />
<ComponentGroupRef Id="ArpEntry" />
</Feature>
<!--
Friendly install UI. WixToolset.UI.wixext provides several flavors;
WixUI_InstallDir lets the user pick the directory.
-->
<ui:WixUI Id="WixUI_InstallDir" />
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLFOLDER" />
<!--
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/teamsiso" />
<Property Id="ARPURLINFOABOUT" Value="https://wilddragon.net" />
<Property Id="ARPCONTACT" Value="Wild Dragon LLC — support@wilddragon.net" />
<Property Id="ARPCOMMENTS" Value="TeamsISO 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_InstallDir; don't redeclare. -->
<Property Id="ARPNOREPAIR" Value="1" />
feat: app icon, FPS, drops counter, --version, About dialog, Stop Teams toggle Six related polish items, all building on tonight's groundwork. 1. App icon: teamsiso.ico generated from dragon-mark.png at 7 sizes (16-256), wired as ApplicationIcon in the WPF csproj, MainWindow.Icon, AboutWindow.Icon, and ARPPRODUCTICON in the WiX MSI. Taskbar / window / Add-Remove-Programs all show the dragon mark now. 2. Running incoming FPS: ring buffer of last 30 frame timestamps in IsoPipeline; ComputeFps() returns moving-average rate. Surfaced on IsoHealthStats.IncomingFps and shown in the Source column of the participants DataGrid as 'WxH · 59.94 fps'. Resets cleanly on every supervisor restart. 3. Drops counter: FrameProcessor.Stats already aggregated FramesDropped (closest-frame strategy when the receiver outpaces the processor) and FramesDuplicated; just plumbed _liveProcessor through IsoPipeline so GetStats() can read them. Exposed in the Live column under the in/out counters as a coral-tinted 'drop N'. 4. Console --version flag: prints engine version (with embedded git SHA), .NET version, OS, NDI runtime banner, expected prefix, exit-code legend, plus a wilddragon.net link. Useful for support tickets. 5. About dialog: chromeless modal with the dragon mark + version / .NET / OS / NDI runtime fields and a link to wilddragon.net. Triggered by clicking the rail logo. 6. Teams launcher Stop toggle: TeamsLauncher gains IsRunning() and StopAll(). The rail's Teams button now toggles — if Teams is up, ask to close all Teams windows via WM_CLOSE; otherwise launch as before. Confirms before stopping so we don't kill the user's call mid-transition. Tests: 74/74 unit + 9/9 NDI integration green throughout. MSI builds clean and now embeds the dragon icon for ARP.
2026-05-08 13:50:19 -04:00
<!--
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 published copy under src/TeamsISO.App/Assets so the icon
embedded in the MSI matches the icon in the running exe.
-->
<Icon Id="TeamsISOIcon" SourceFile="$(var.AssetsDir)teamsiso.ico" />
<Property Id="ARPPRODUCTICON" Value="TeamsISOIcon" />
<!--
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\TeamsISO.
-->
<StandardDirectory Id="ProgramFiles64Folder">
<Directory Id="ManufacturerFolder" Name="Wild Dragon">
<Directory Id="INSTALLFOLDER" Name="TeamsISO" />
</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>
<!--
fix(installer+wpf): REVERT runas /trustlevel demotion (it was the bug, not the fix) Massive misdiagnosis correction. The 2025-05-16 effort to 'fix elevation' has been actively breaking every Start Menu / Desktop shortcut launch since rc7. Empirical retrace: - Elevated PowerShell -> Process.Start(exe) -> elevated TeamsISO -> WORKS - Elevated PowerShell with --keep-elevation -> elevated TeamsISO -> WORKS (vm.Participants.Count=2) - Non-elevated PS Process.Start(exe) -> medium TeamsISO -> WORKS - ANY launch through runas /trustlevel:0x20000 -> SAFER-restricted TeamsISO -> BROKEN (window appears, zero managed code runs past BAML parse, no logs, no port binds) The SAFER-restricted token that runas /trustlevel produces breaks .NET 8 WPF apphost in a way that leaves the process apparently alive (with the MainWindow.xaml rendering the empty state from default property values) but executing zero managed code. So my StartupTrace, Serilog file sink, and ControlSurface bind all silently failed for every shortcut launch. Looked exactly like 'cold-start NDI Find stuck at zero' from the outside but had nothing to do with NDI. Revert: - installer/Package.wxs: shortcuts target the .exe directly, no runas wrapper - App.xaml.cs: removed ShouldDeElevate, TryDeElevateAndExit, RelaunchEnvVar, --keep-elevation/--relaunched handling. The check is gone, not just disabled, so future-me can't bring it back without re-discovering the same bug. Kept: - StartupTrace (still useful for any future startup mystery) - Self-healing NDI Find rebuild (c30a616) - still valuable for legitimate stuck-finder cases - System.Management PackageReference - TryGetParentProcessName still used in StartupTrace Verified post-revert: Start Menu shortcut click -> PID 43060 -> full trace -> REST 2 participants. 252/252 tests still passing.
2026-05-16 16:27:23 -04:00
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 TeamsISO inherit the launching
token (medium or high integrity, doesn't matter) is the correct
behavior. NDI discovery works fine at either integrity level.
-->
<ComponentGroup Id="Shortcuts" Directory="WildDragonStartMenuFolder">
<Component Id="StartMenuShortcut" Guid="*">
<Shortcut Id="StartMenuTeamsISO"
Name="TeamsISO"
Description="Per-Participant NDI ISO Controller for Microsoft Teams"
fix(installer+wpf): REVERT runas /trustlevel demotion (it was the bug, not the fix) Massive misdiagnosis correction. The 2025-05-16 effort to 'fix elevation' has been actively breaking every Start Menu / Desktop shortcut launch since rc7. Empirical retrace: - Elevated PowerShell -> Process.Start(exe) -> elevated TeamsISO -> WORKS - Elevated PowerShell with --keep-elevation -> elevated TeamsISO -> WORKS (vm.Participants.Count=2) - Non-elevated PS Process.Start(exe) -> medium TeamsISO -> WORKS - ANY launch through runas /trustlevel:0x20000 -> SAFER-restricted TeamsISO -> BROKEN (window appears, zero managed code runs past BAML parse, no logs, no port binds) The SAFER-restricted token that runas /trustlevel produces breaks .NET 8 WPF apphost in a way that leaves the process apparently alive (with the MainWindow.xaml rendering the empty state from default property values) but executing zero managed code. So my StartupTrace, Serilog file sink, and ControlSurface bind all silently failed for every shortcut launch. Looked exactly like 'cold-start NDI Find stuck at zero' from the outside but had nothing to do with NDI. Revert: - installer/Package.wxs: shortcuts target the .exe directly, no runas wrapper - App.xaml.cs: removed ShouldDeElevate, TryDeElevateAndExit, RelaunchEnvVar, --keep-elevation/--relaunched handling. The check is gone, not just disabled, so future-me can't bring it back without re-discovering the same bug. Kept: - StartupTrace (still useful for any future startup mystery) - Self-healing NDI Find rebuild (c30a616) - still valuable for legitimate stuck-finder cases - System.Management PackageReference - TryGetParentProcessName still used in StartupTrace Verified post-revert: Start Menu shortcut click -> PID 43060 -> full trace -> REST 2 participants. 252/252 tests still passing.
2026-05-16 16:27:23 -04:00
Target="[INSTALLFOLDER]TeamsISO.exe"
WorkingDirectory="INSTALLFOLDER"
fix(installer+wpf): REVERT runas /trustlevel demotion (it was the bug, not the fix) Massive misdiagnosis correction. The 2025-05-16 effort to 'fix elevation' has been actively breaking every Start Menu / Desktop shortcut launch since rc7. Empirical retrace: - Elevated PowerShell -> Process.Start(exe) -> elevated TeamsISO -> WORKS - Elevated PowerShell with --keep-elevation -> elevated TeamsISO -> WORKS (vm.Participants.Count=2) - Non-elevated PS Process.Start(exe) -> medium TeamsISO -> WORKS - ANY launch through runas /trustlevel:0x20000 -> SAFER-restricted TeamsISO -> BROKEN (window appears, zero managed code runs past BAML parse, no logs, no port binds) The SAFER-restricted token that runas /trustlevel produces breaks .NET 8 WPF apphost in a way that leaves the process apparently alive (with the MainWindow.xaml rendering the empty state from default property values) but executing zero managed code. So my StartupTrace, Serilog file sink, and ControlSurface bind all silently failed for every shortcut launch. Looked exactly like 'cold-start NDI Find stuck at zero' from the outside but had nothing to do with NDI. Revert: - installer/Package.wxs: shortcuts target the .exe directly, no runas wrapper - App.xaml.cs: removed ShouldDeElevate, TryDeElevateAndExit, RelaunchEnvVar, --keep-elevation/--relaunched handling. The check is gone, not just disabled, so future-me can't bring it back without re-discovering the same bug. Kept: - StartupTrace (still useful for any future startup mystery) - Self-healing NDI Find rebuild (c30a616) - still valuable for legitimate stuck-finder cases - System.Management PackageReference - TryGetParentProcessName still used in StartupTrace Verified post-revert: Start Menu shortcut click -> PID 43060 -> full trace -> REST 2 participants. 252/252 tests still passing.
2026-05-16 16:27:23 -04:00
Icon="TeamsISOIcon" />
<!-- 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\TeamsISO"
Name="StartMenuShortcut"
Type="integer"
Value="1"
KeyPath="yes" />
</Component>
</ComponentGroup>
fix: cold-start discovery + installer shortcuts + single-instance hardening Three independent fixes bundled because all were chasing the same operator report: 'I just installed, launched from the shortcut, no participants.' 1) NdiDiscoveryService: poll immediately, then ramp from 200ms to the configured interval over the first 3 seconds. PeriodicTimer.WaitForNext- TickAsync waits the full interval before its first tick, so for a 500ms discovery interval the operator stared at 'no ndi sources yet' for half a second on every cold start. Force-poll up front (catches the runtime cache), then run a fast inner loop for ~3s while mDNS replies trickle in. Both loops share a try/finally so the NDI finder is always disposed. 2) MainViewModel.IsDiscovering: new boolean, true for 8s after engine start AS LONG AS no participants have arrived. MainWindow.xaml swaps the empty-state copy on this binding: IsDiscovering=true -> 'scanning for ndi sources...' (cyan dot) IsDiscovering=false -> 'no ndi sources visible -- is teams in a meeting?' + Refresh CTA The old copy ('no ndi sources yet -- open teams and start a meeting') was being shown immediately at launch even when discovery just hadn't run yet, making the app look broken. 3) App.xaml.cs: single-instance mutex moved from Local\ to Global\. On admin-user boxes with UAC disabled, launches from different parents (elevated File Explorer, non-elevated shell, etc.) can land in slightly different security contexts and a Local\ name can be invisible to the sibling. Global\ namespace closes that hole — both processes see the same mutex regardless of integrity. Belt-and-braces against future dual-instance file/port contention. 4) installer/Package.wxs: add a Desktop shortcut component (per-machine feature, HKCU keypath per ICE38/ICE43). Operators who can't find the Start Menu entry get the Desktop icon. Both shortcuts target the installed exe, NOT a stale path under publish/.
2026-05-16 11:23:19 -04:00
<StandardDirectory Id="DesktopFolder" />
<ComponentGroup Id="DesktopShortcut" Directory="DesktopFolder">
<Component Id="DesktopShortcutComponent" Guid="*">
<Shortcut Id="DesktopTeamsISO"
Name="TeamsISO"
Description="Per-Participant NDI ISO Controller for Microsoft Teams"
fix(installer+wpf): REVERT runas /trustlevel demotion (it was the bug, not the fix) Massive misdiagnosis correction. The 2025-05-16 effort to 'fix elevation' has been actively breaking every Start Menu / Desktop shortcut launch since rc7. Empirical retrace: - Elevated PowerShell -> Process.Start(exe) -> elevated TeamsISO -> WORKS - Elevated PowerShell with --keep-elevation -> elevated TeamsISO -> WORKS (vm.Participants.Count=2) - Non-elevated PS Process.Start(exe) -> medium TeamsISO -> WORKS - ANY launch through runas /trustlevel:0x20000 -> SAFER-restricted TeamsISO -> BROKEN (window appears, zero managed code runs past BAML parse, no logs, no port binds) The SAFER-restricted token that runas /trustlevel produces breaks .NET 8 WPF apphost in a way that leaves the process apparently alive (with the MainWindow.xaml rendering the empty state from default property values) but executing zero managed code. So my StartupTrace, Serilog file sink, and ControlSurface bind all silently failed for every shortcut launch. Looked exactly like 'cold-start NDI Find stuck at zero' from the outside but had nothing to do with NDI. Revert: - installer/Package.wxs: shortcuts target the .exe directly, no runas wrapper - App.xaml.cs: removed ShouldDeElevate, TryDeElevateAndExit, RelaunchEnvVar, --keep-elevation/--relaunched handling. The check is gone, not just disabled, so future-me can't bring it back without re-discovering the same bug. Kept: - StartupTrace (still useful for any future startup mystery) - Self-healing NDI Find rebuild (c30a616) - still valuable for legitimate stuck-finder cases - System.Management PackageReference - TryGetParentProcessName still used in StartupTrace Verified post-revert: Start Menu shortcut click -> PID 43060 -> full trace -> REST 2 participants. 252/252 tests still passing.
2026-05-16 16:27:23 -04:00
Target="[INSTALLFOLDER]TeamsISO.exe"
fix: cold-start discovery + installer shortcuts + single-instance hardening Three independent fixes bundled because all were chasing the same operator report: 'I just installed, launched from the shortcut, no participants.' 1) NdiDiscoveryService: poll immediately, then ramp from 200ms to the configured interval over the first 3 seconds. PeriodicTimer.WaitForNext- TickAsync waits the full interval before its first tick, so for a 500ms discovery interval the operator stared at 'no ndi sources yet' for half a second on every cold start. Force-poll up front (catches the runtime cache), then run a fast inner loop for ~3s while mDNS replies trickle in. Both loops share a try/finally so the NDI finder is always disposed. 2) MainViewModel.IsDiscovering: new boolean, true for 8s after engine start AS LONG AS no participants have arrived. MainWindow.xaml swaps the empty-state copy on this binding: IsDiscovering=true -> 'scanning for ndi sources...' (cyan dot) IsDiscovering=false -> 'no ndi sources visible -- is teams in a meeting?' + Refresh CTA The old copy ('no ndi sources yet -- open teams and start a meeting') was being shown immediately at launch even when discovery just hadn't run yet, making the app look broken. 3) App.xaml.cs: single-instance mutex moved from Local\ to Global\. On admin-user boxes with UAC disabled, launches from different parents (elevated File Explorer, non-elevated shell, etc.) can land in slightly different security contexts and a Local\ name can be invisible to the sibling. Global\ namespace closes that hole — both processes see the same mutex regardless of integrity. Belt-and-braces against future dual-instance file/port contention. 4) installer/Package.wxs: add a Desktop shortcut component (per-machine feature, HKCU keypath per ICE38/ICE43). Operators who can't find the Start Menu entry get the Desktop icon. Both shortcuts target the installed exe, NOT a stale path under publish/.
2026-05-16 11:23:19 -04:00
WorkingDirectory="INSTALLFOLDER"
fix(installer+wpf): REVERT runas /trustlevel demotion (it was the bug, not the fix) Massive misdiagnosis correction. The 2025-05-16 effort to 'fix elevation' has been actively breaking every Start Menu / Desktop shortcut launch since rc7. Empirical retrace: - Elevated PowerShell -> Process.Start(exe) -> elevated TeamsISO -> WORKS - Elevated PowerShell with --keep-elevation -> elevated TeamsISO -> WORKS (vm.Participants.Count=2) - Non-elevated PS Process.Start(exe) -> medium TeamsISO -> WORKS - ANY launch through runas /trustlevel:0x20000 -> SAFER-restricted TeamsISO -> BROKEN (window appears, zero managed code runs past BAML parse, no logs, no port binds) The SAFER-restricted token that runas /trustlevel produces breaks .NET 8 WPF apphost in a way that leaves the process apparently alive (with the MainWindow.xaml rendering the empty state from default property values) but executing zero managed code. So my StartupTrace, Serilog file sink, and ControlSurface bind all silently failed for every shortcut launch. Looked exactly like 'cold-start NDI Find stuck at zero' from the outside but had nothing to do with NDI. Revert: - installer/Package.wxs: shortcuts target the .exe directly, no runas wrapper - App.xaml.cs: removed ShouldDeElevate, TryDeElevateAndExit, RelaunchEnvVar, --keep-elevation/--relaunched handling. The check is gone, not just disabled, so future-me can't bring it back without re-discovering the same bug. Kept: - StartupTrace (still useful for any future startup mystery) - Self-healing NDI Find rebuild (c30a616) - still valuable for legitimate stuck-finder cases - System.Management PackageReference - TryGetParentProcessName still used in StartupTrace Verified post-revert: Start Menu shortcut click -> PID 43060 -> full trace -> REST 2 participants. 252/252 tests still passing.
2026-05-16 16:27:23 -04:00
Icon="TeamsISOIcon" />
fix: cold-start discovery + installer shortcuts + single-instance hardening Three independent fixes bundled because all were chasing the same operator report: 'I just installed, launched from the shortcut, no participants.' 1) NdiDiscoveryService: poll immediately, then ramp from 200ms to the configured interval over the first 3 seconds. PeriodicTimer.WaitForNext- TickAsync waits the full interval before its first tick, so for a 500ms discovery interval the operator stared at 'no ndi sources yet' for half a second on every cold start. Force-poll up front (catches the runtime cache), then run a fast inner loop for ~3s while mDNS replies trickle in. Both loops share a try/finally so the NDI finder is always disposed. 2) MainViewModel.IsDiscovering: new boolean, true for 8s after engine start AS LONG AS no participants have arrived. MainWindow.xaml swaps the empty-state copy on this binding: IsDiscovering=true -> 'scanning for ndi sources...' (cyan dot) IsDiscovering=false -> 'no ndi sources visible -- is teams in a meeting?' + Refresh CTA The old copy ('no ndi sources yet -- open teams and start a meeting') was being shown immediately at launch even when discovery just hadn't run yet, making the app look broken. 3) App.xaml.cs: single-instance mutex moved from Local\ to Global\. On admin-user boxes with UAC disabled, launches from different parents (elevated File Explorer, non-elevated shell, etc.) can land in slightly different security contexts and a Local\ name can be invisible to the sibling. Global\ namespace closes that hole — both processes see the same mutex regardless of integrity. Belt-and-braces against future dual-instance file/port contention. 4) installer/Package.wxs: add a Desktop shortcut component (per-machine feature, HKCU keypath per ICE38/ICE43). Operators who can't find the Start Menu entry get the Desktop icon. Both shortcuts target the installed exe, NOT a stale path under publish/.
2026-05-16 11:23:19 -04:00
<RegistryValue Root="HKCU"
Key="Software\Wild Dragon\TeamsISO"
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 point at the
executable for the ARP icon.
-->
<ComponentGroup Id="ArpEntry" Directory="INSTALLFOLDER">
<Component Id="ArpIconRegistry" Guid="*">
<RegistryValue Root="HKLM"
Key="Software\Wild Dragon\TeamsISO"
Name="InstallPath"
Type="string"
Value="[INSTALLFOLDER]"
KeyPath="yes" />
</Component>
</ComponentGroup>
</Package>
</Wix>