[fix] fix: guard GenerateProgramFile target against UseWinUI/UseUwpTools evaluation order - #16072
Conversation
When UseWinUI or UseUwpTools is set by the Windows App SDK package targets, it may be set AFTER Microsoft.NET.Test.Sdk.targets property evaluation runs (due to NuGet import order). This causes the static PropertyGroup check on line 33 to miss UseWinUI=true, leaving GenerateProgramFile=true and triggering CS0017 (multiple entry points). The fix adds the same UseWinUI/UseUwpTools guard to the target's Condition, so the entry-point file is never generated for WinUI or UWP test apps regardless of property evaluation order. Fixes #16071 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR fixes Microsoft.NET.Test.Sdk.targets so WinUI/UWP test apps do not generate an extra SDK Main entry point when UseWinUI or UseUwpTools is evaluated later in the MSBuild import order.
Changes:
- Adds
UseWinUI/UseUwpToolsguards directly to theGenerateProgramFiletarget condition. - Keeps target execution consistent with the existing comments and property defaults for WinUI/UWP apps.
Jakub Jareš (nohwnd)
left a comment
There was a problem hiding this comment.
🧠 Expert Review — PR #16072
Scope: 1 file changed, 1 line modified (Microsoft.NET.Test.Sdk.targets)
Analysis
The fix is correct and well-reasoned. The root cause — MSBuild InitialTargets running before NuGet package targets (alphabetically sorted) set UseWinUI — is a real evaluation-order hazard, and the solution is the right one: move the guard to the target's own Condition, which is re-evaluated at execution time after all imports are processed.
Checked dimensions:
- ✅ Algorithmic correctness: The redundant guard (
'$(GenerateProgramFile)' == 'true' AND UseWinUI != true) is safe — ifGenerateProgramFilewas correctly set tofalseby the PropertyGroup, the target would already be skipped. The new conditions add defense-in-depth for the race window. No logic inversion. - ✅ MSBuild contract:
Target/@Condition`` is evaluated at target execution time, not import time — this is the correct MSBuild mechanism for this scenario. - ✅ Consistency: The new condition mirrors the existing
OutputTypeguard on line 21 ('$(UseWinUI)' != 'true' AND '$(UseUwpTools)' != 'true'), keeping the file internally consistent. - ✅ Description alignment: PR title and body accurately describe the change, root cause, and fix rationale.
- ✅ No API surface changes, no binding redirect implications, no nupkg file count changes.
No issues found. This is a clean, minimal fix.
🧠 Reviewed by Expert Code Reviewer
🧠 Reviewed by Expert Code Reviewer 🧠
🤖 Expert vstest review (automated)Small, surgical one-line change to 🛑 BlockersNone.
|
|
Thanks for the thorough review Acknowledging the follow-up items:
CI is green across all jobs. The fix is ready for merge when you are.
|
Fixes #16071
Root Cause
Microsoft.NET.Test.Sdk.targetsusesInitialTargets="GenerateProgramFile"so theGenerateProgramFiletarget runs before any user targets. ThePropertyGroupat the top of the file tries to setGenerateProgramFile=falsewhenUseWinUI=true:However, when
UseWinUIis not set explicitly in the project file but is instead set by the Windows App SDK's own NuGet package targets, the import order matters. NuGet package targets are auto-imported alphabetically;Microsoft.NET.Test.Sdksorts beforeWindowsAppSDK, so the Test SDK's PropertyGroup is evaluated whenUseWinUIis still empty. As a result,GenerateProgramFileends up set totrue, and theGenerateProgramFiletarget generates aProgram.cswith aMainmethod — conflicting with the entry point that the WinUI XAML compiler generates, causing CS0017: Program has more than one entry point defined.Fix
Add the same
UseWinUI/UseUwpToolsguard directly to the target'sCondition, so even ifGenerateProgramFilewas incorrectly set totrueduring static property evaluation, the target will never execute for WinUI or UWP test apps:Target conditions are re-evaluated at execution time, by which point all package targets have been imported and
UseWinUIis correctly set.Testing
The fix is a one-line change in a
.targetsfile. The change makes theGenerateProgramFiletarget's behaviour consistent with the comment in the file ("We always skip the generated entry point for UWP apps... We also do the same for WinUI apps").A targeted acceptance test for this scenario would require a WinUI test project on Windows with the Windows App SDK — that environment is not available in this CI setup. The logic change mirrors the existing
OutputTypeguard on line 21 of the same file.