Skip to content

Gate WiX 3 and WiX 5 toolset downloads behind opt-in properties#16612

Draft
Copilot wants to merge 2 commits intomainfrom
copilot/fix-wix-toolset-requirements
Draft

Gate WiX 3 and WiX 5 toolset downloads behind opt-in properties#16612
Copilot wants to merge 2 commits intomainfrom
copilot/fix-wix-toolset-requirements

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 19, 2026

Every repo using Arcade SDK 10 was unconditionally downloading both Microsoft.Signed.Wix (WiX 3) and Microsoft.WixToolset.Sdk (WiX 5) toolsets — including repos that produce no MSI/WiX installers — causing unnecessary ~100MB+ restores and signing failures when WiX feeds are unavailable.

Changes

  • DefaultVersions.props — Added two new opt-in properties (default false), following the UsingToolVSSDK pattern:

    <UsingToolWix3 Condition="'$(UsingToolWix3)' == ''">false</UsingToolWix3>
    <UsingToolWix5 Condition="'$(UsingToolWix5)' == ''">false</UsingToolWix5>
  • Tools.proj — Gated both PackageDownload entries behind their respective opt-in:

    <PackageDownload Include="Microsoft.Signed.Wix" ... Condition="'$(UsingToolWix3)' == 'true'" />
    <PackageDownload Include="Microsoft.WixToolset.Sdk" ... Condition="'$(UsingToolWix5)' == 'true'" />
  • Sign.proj — Gated Microsoft.Signed.Wix.props import and conditionally sets _Wix3ToolsPath/_WixToolsPath only when the respective tool is opted in; passes those to SignToolTask instead of unconditional property expansions.

  • SignToolTask.cs / BatchSignUtil.cs — Changed WiX path guards from != null / == null to !string.IsNullOrEmpty() to correctly handle MSBuild's empty-string expansion of unset properties.

Repos producing WiX installers must now set <UsingToolWix3>true</UsingToolWix3> and/or <UsingToolWix5>true</UsingToolWix5> in eng/Versions.props.

To double check:

Original prompt

This section details on the original issue you should resolve

<issue_title>Sign.proj and Tools.proj unconditionally require both WiX 3 and WiX 5 toolsets</issue_title>
<issue_description>## Summary

Sign.proj and Tools.proj unconditionally reference both WiX 3 (Microsoft.Signed.Wix) and WiX 5 (Microsoft.WixToolset.Sdk) toolset packages, forcing every repo using Arcade SDK 10 to download and validate both — even repos that produce no MSI/WiX installers at all.

This was introduced by PR #15962 ("Wix 5 signing support", merged 2025-07-14).

Repro

Any repo onboarded to Arcade SDK 10.0.0-beta.* (e.g. a NuGet-only repo with no WiX usage) will restore both WiX packages and SignToolTask will validate both tool paths exist.

Root Cause

Three files contribute to the problem:

1. DefaultVersions.props — unconditionally sets both versions

<MicrosoftSignedWixVersion Condition="'$(MicrosoftSignedWixVersion)' == ''">3.14.1-9323.2545153</MicrosoftSignedWixVersion>
<MicrosoftWixToolsetSdkVersion Condition="'$(MicrosoftWixToolsetSdkVersion)' == ''">5.0.2-dotnet.2811440</MicrosoftWixToolsetSdkVersion>

2. Tools.proj — unconditionally downloads both packages (no opt-in gate)

<PackageReference Include="Microsoft.Signed.Wix" Version="$(MicrosoftSignedWixVersion)" IsImplicitlyDefined="true" />
<PackageReference Include="Microsoft.WixToolset.Sdk" Version="$(MicrosoftWixToolsetSdkVersion)" IsImplicitlyDefined="true" />

Compare with Microsoft.DotNet.Build.Tasks.VisualStudio which is gated behind UsingToolVSSDK:

<PackageReference Include="Microsoft.DotNet.Build.Tasks.VisualStudio" ... Condition="'$(UsingToolVSSDK)' == 'true'" />

3. Sign.proj — unconditionally passes both tool paths to SignToolTask

Wix3ToolsPath="$(WixInstallPath)"
WixToolsPath="$(NuGetPackageRoot)microsoft.wixtoolset.sdk\$(MicrosoftWixToolsetSdkVersion)\tools\net472\x64"

4. SignToolTask — validates both paths and errors if set but missing

if (Wix3ToolsPath != null && !Directory.Exists(Wix3ToolsPath))
    Log.LogError($"Wix3ToolsPath ('{ Wix3ToolsPath}') does not exist.");
if (WixToolsPath != null && !Directory.Exists(WixToolsPath))
    Log.LogError($"WixToolsPath ('{ WixToolsPath}') does not exist.");

Impact

  • Repos that only produce NuGet packages (no MSIs/wixpacks) are forced to download ~100MB+ of WiX tooling they never use
  • If WiX packages fail to restore (feed issues, network), signing breaks even though no WiX artifacts exist
  • The wixpack files used to zip and sign MSIs differ between WiX 3 and WiX 5, and SignToolTask expects both toolsets to be present even if only one version is in use

Suggested Fix

Gate WiX toolset references behind an opt-in property (similar to UsingToolVSSDK):

<!-- Tools.proj -->
<PackageReference Include="Microsoft.Signed.Wix" ... Condition="'$(UsingToolWix3)' == 'true' or '$(UsingToolWix)' == 'true'" />
<PackageReference Include="Microsoft.WixToolset.Sdk" ... Condition="'$(UsingToolWix5)' == 'true' or '$(UsingToolWix)' == 'true'" />
<!-- Sign.proj -->
Wix3ToolsPath="$(WixInstallPath)" Condition="'$(UsingToolWix3)' == 'true' or '$(UsingToolWix)' == 'true'"
WixToolsPath="..." Condition="'$(UsingToolWix5)' == 'true' or '$(UsingToolWix)' == 'true'"

Or at minimum, only pass the tool paths when the corresponding version property is explicitly set by the repo (not just defaulted).

Environment

  • Arcade SDK: 10.0.0-beta.26168.104
  • Source: dotnet/dotnet VMR @ 73b3b5ac0e4a5658c7a0555b67d91a22ad39de4b
  • Affected repo: dotnet/maui-labs (NuGet packages only, no WiX installers)

/cc @NikolaMilosavljevic @joeloff</issue_description>

Comments on the Issue (you are @copilot in this section)


💬 Send tasks to Copilot coding agent from Slack and Teams to turn conversations into code. Copilot posts an update in your thread when it's finished.

Co-authored-by: rmarinho <1235097+rmarinho@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix unneeded WiX 3 and WiX 5 toolset requirements Gate WiX 3 and WiX 5 toolset downloads behind opt-in properties Mar 19, 2026
Copilot AI requested a review from rmarinho March 19, 2026 15:16
@rmarinho
Copy link
Copy Markdown
Member

@copilot when should this true by default? where ele is Wix opted in?

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 19, 2026

@copilot when should this true by default? where ele is Wix opted in?

Neither property should ever be true by default — they're opt-in, just like UsingToolVSSDK. Only repos that actually produce WiX-based MSI installers or bundles (wixpacks) need to set them in their eng/Versions.props.

Who should opt in:

  • Repos using WiX 3 (light.exe-based MSIs) set <UsingToolWix3>true</UsingToolWix3>
  • Repos using WiX 5 (wix.exe-based MSIs, UseWix5 property at the project level) set <UsingToolWix5>true</UsingToolWix5>
  • NuGet-only repos like dotnet/maui-labs don't set either and skip the ~100MB WiX download entirely

Where WiX is currently consumed in Arcade's infrastructure:

  • src/Microsoft.DotNet.Build.Tasks.Installers/build/installer.build.targets — imports wix/wix.targets or wix5/wix.targets based on the UseWix5 project-level property
  • src/Microsoft.DotNet.Build.Tasks.Installers/build/bundle.targets — same conditional import for exe bundle generation
  • src/Microsoft.DotNet.SignTool — uses Wix3ToolsPath/WixToolsPath only when signing wixpack.zip files

@rmarinho
Copy link
Copy Markdown
Member

@mmitche @joeloff any ideas here?

<UsingToolVisualStudioIbcTraining Condition="'$(UsingToolVisualStudioIbcTraining)' == ''">false</UsingToolVisualStudioIbcTraining>
<UsingToolNuGetRepack Condition="'$(UsingToolNuGetRepack)' == ''">false</UsingToolNuGetRepack>
<UsingToolSymbolUploader Condition="'$(UsingToolSymbolUploader)' == ''">false</UsingToolSymbolUploader>
<!-- Set UsingToolWix3 to true if this repo produces WiX 3 MSI installers (wixpacks). -->
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defautling to false will be a breaking change for downstream repos. I'd default to true

<!-- Set UsingToolWix3 to true if this repo produces WiX 3 MSI installers (wixpacks). -->
<UsingToolWix3 Condition="'$(UsingToolWix3)' == ''">false</UsingToolWix3>
<!-- Set UsingToolWix5 to true if this repo produces WiX 5 MSI installers (wixpacks). -->
<UsingToolWix5 Condition="'$(UsingToolWix5)' == ''">false</UsingToolWix5>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand our upgrade path correct, UsingToolWix5 will be incorrectly named when we update to 6 or 7. Instead, maybe UsingToolWix5Plus?

Copy link
Copy Markdown
Member

@mmitche mmitche left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in general this looks okay but needs tweaks around the defaults OR we need to identifyt all the places that need to get the property and update before we check in. Most of the time this wouldn't break a repo until it ran its official build.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sign.proj and Tools.proj unconditionally require both WiX 3 and WiX 5 toolsets

3 participants