Skip to content

Commit 12161d3

Browse files
authored
Add clear error message (MSB4233) for .NET runtime tasks on MSBuild 17.14 (#12662)
1 parent e402909 commit 12161d3

File tree

17 files changed

+146
-1
lines changed

17 files changed

+146
-1
lines changed

eng/Versions.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the MIT license. See License.txt in the project root for full license information. -->
33
<Project>
44
<PropertyGroup>
5-
<VersionPrefix>17.14.32</VersionPrefix>
5+
<VersionPrefix>17.14.33</VersionPrefix>
66
<DotNetFinalVersionKind>release</DotNetFinalVersionKind>
77
<PackageValidationBaselineVersion>17.13.9</PackageValidationBaselineVersion>
88
<AssemblyVersion>15.1.0.0</AssemblyVersion>
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.IO;
6+
using Microsoft.Build.Execution;
7+
using Microsoft.Build.UnitTests;
8+
using Shouldly;
9+
using Xunit;
10+
using Xunit.Abstractions;
11+
12+
namespace Microsoft.Build.Engine.UnitTests.BackEnd
13+
{
14+
/// <summary>
15+
/// End-to-end MSBuild CLI tests for .NET Runtime task error handling.
16+
/// These tests verify that MSBuild.exe CLI gives a clear error when attempting to use Runtime="NET" tasks.
17+
/// </summary>
18+
public class DotNetTaskHost_Tests
19+
{
20+
private readonly ITestOutputHelper _output;
21+
22+
public DotNetTaskHost_Tests(ITestOutputHelper output)
23+
{
24+
_output = output;
25+
}
26+
27+
/// <summary>
28+
/// Test that MSBuild.exe gives clear error (MSB4233) when building a project
29+
/// that uses a task with Runtime="NET".
30+
/// </summary>
31+
[WindowsFullFrameworkOnlyFact]
32+
public void CustomTask_WithNetRuntime_ShowsClearError()
33+
{
34+
#if NETFRAMEWORK
35+
using (var env = TestEnvironment.Create(_output))
36+
{
37+
string taskAssemblyPath = Path.Combine(
38+
Path.GetDirectoryName(typeof(DotNetTaskHost_Tests).Assembly.Location) ?? AppContext.BaseDirectory,
39+
"Microsoft.Build.Engine.UnitTests.dll");
40+
41+
string projectContent = $@"
42+
<Project>
43+
<UsingTask TaskName=""ProcessIdTask"" AssemblyFile=""{taskAssemblyPath}"" Runtime=""NET"" />
44+
<Target Name='TestTask'>
45+
<ProcessIdTask>
46+
<Output PropertyName=""PID"" TaskParameter=""Pid"" />
47+
</ProcessIdTask>
48+
</Target>
49+
</Project>";
50+
var logger = new MockLogger(_output);
51+
TransientTestFile project = env.CreateFile("test.csproj", projectContent);
52+
ProjectInstance projectInstance = new(project.Path);
53+
projectInstance.Build(new[] { logger })
54+
.ShouldBeFalse();
55+
56+
logger.ErrorCount.ShouldBeGreaterThan(0);
57+
logger.Errors[0].Code.ShouldBe("MSB4233");
58+
}
59+
#endif
60+
}
61+
}
62+
}

src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,20 @@ internal static string GetMSBuildLocationFromHostContext(HandshakeOptions hostCo
486486
/// </summary>
487487
internal bool AcquireAndSetUpHost(HandshakeOptions hostContext, INodePacketFactory factory, INodePacketHandler handler, TaskHostConfiguration configuration)
488488
{
489+
#if NETFRAMEWORK
490+
// MSB4233: Check if .NET runtime is requested, which is not supported in .NET Framework builds of MSBuild (17.14 and earlier).
491+
// All .NET Core/5+ MSBuilds and all 18.0+ builds do support .NET runtime tasks, so this check is not needed there.
492+
// This provides a clear error message instead of the confusing "MSBuild.dll not found" error that would otherwise occur.
493+
if ((hostContext & HandshakeOptions.NET) == HandshakeOptions.NET)
494+
{
495+
ProjectFileErrorUtilities.ThrowInvalidProjectFile(
496+
new BuildEventFileInfo(configuration.ProjectFileOfTask, configuration.LineNumberOfTask, configuration.ColumnNumberOfTask),
497+
"TaskRuntimeNET",
498+
configuration.TaskName,
499+
configuration.TaskLocation);
500+
}
501+
#endif
502+
489503
bool nodeCreationSucceeded;
490504
if (!_nodeContexts.ContainsKey(hostContext))
491505
{

src/Build/Resources/Strings.resx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,6 +1238,10 @@
12381238
<value>MSB4217: Task host node exited prematurely. Diagnostic information may be found in files in the temporary files directory named MSBuild_*.failure.txt. {0}</value>
12391239
<comment>{StrBegin="MSB4217: "}</comment>
12401240
</data>
1241+
<data name="TaskRuntimeNET" xml:space="preserve">
1242+
<value>MSB4233: The task "{0}" from assembly "{1}" was specified to load with the .NET runtime, but this version of MSBuild does not support loading tasks with that runtime. To run .NET tasks, use "dotnet build" or Visual Studio 2026 or higher.</value>
1243+
<comment>{StrBegin="MSB4233: "}{Locked=".NET"}{Locked="dotnet build"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, dotnet build, and Visual Studio 2026 should not be localized.</comment>
1244+
</data>
12411245
<data name="TaskParametersError" xml:space="preserve">
12421246
<value>MSB4063: The "{0}" task could not be initialized with its input parameters. {1}</value>
12431247
<comment>{StrBegin="MSB4063: "}</comment>

src/Build/Resources/xlf/Strings.cs.xlf

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Build/Resources/xlf/Strings.de.xlf

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Build/Resources/xlf/Strings.es.xlf

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Build/Resources/xlf/Strings.fr.xlf

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Build/Resources/xlf/Strings.it.xlf

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Build/Resources/xlf/Strings.ja.xlf

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)