From 2b0154ec24b46ded8d372aedc934350b7b26d794 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Oct 2025 15:31:14 +0000 Subject: [PATCH 01/15] Add error detection for .NET runtime tasks in older MSBuild versions - Add MSB4233 error string with task name and assembly location - Implement check in AcquireAndSetUpHost to detect HandshakeOptions.NET flag - Verified MSB4233 is not used in main or vs18.0 branches Co-authored-by: baronfel <573979+baronfel@users.noreply.github.com> --- .../NodeProviderOutOfProcTaskHost.cs | 15 +++++++++++++++ src/Build/Resources/Strings.resx | 4 ++++ src/Build/Resources/xlf/Strings.cs.xlf | 5 +++++ src/Build/Resources/xlf/Strings.de.xlf | 5 +++++ src/Build/Resources/xlf/Strings.es.xlf | 5 +++++ src/Build/Resources/xlf/Strings.fr.xlf | 5 +++++ src/Build/Resources/xlf/Strings.it.xlf | 5 +++++ src/Build/Resources/xlf/Strings.ja.xlf | 5 +++++ src/Build/Resources/xlf/Strings.ko.xlf | 5 +++++ src/Build/Resources/xlf/Strings.pl.xlf | 5 +++++ src/Build/Resources/xlf/Strings.pt-BR.xlf | 5 +++++ src/Build/Resources/xlf/Strings.ru.xlf | 5 +++++ src/Build/Resources/xlf/Strings.tr.xlf | 5 +++++ src/Build/Resources/xlf/Strings.zh-Hans.xlf | 5 +++++ src/Build/Resources/xlf/Strings.zh-Hant.xlf | 5 +++++ 15 files changed, 84 insertions(+) diff --git a/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs b/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs index 1d0f0f525d3..a9e16005e78 100644 --- a/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs +++ b/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs @@ -486,6 +486,21 @@ internal static string GetMSBuildLocationFromHostContext(HandshakeOptions hostCo /// internal bool AcquireAndSetUpHost(HandshakeOptions hostContext, INodePacketFactory factory, INodePacketHandler handler, TaskHostConfiguration configuration) { + // Check if .NET runtime is requested, which is not supported in this version + if ((hostContext & HandshakeOptions.NET) == HandshakeOptions.NET) + { + throw new Exceptions.InvalidProjectFileException( + configuration.ProjectFileOfTask, + configuration.LineNumberOfTask, + configuration.ColumnNumberOfTask, + 0, + 0, + ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("TaskRuntimeNET", configuration.TaskName, configuration.TaskLocation), + null, + null, + null); + } + bool nodeCreationSucceeded; if (!_nodeContexts.ContainsKey(hostContext)) { diff --git a/src/Build/Resources/Strings.resx b/src/Build/Resources/Strings.resx index 88b068552be..9137320262c 100644 --- a/src/Build/Resources/Strings.resx +++ b/src/Build/Resources/Strings.resx @@ -1238,6 +1238,10 @@ MSB4217: Task host node exited prematurely. Diagnostic information may be found in files in the temporary files directory named MSBuild_*.failure.txt. {0} {StrBegin="MSB4217: "} + + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + MSB4063: The "{0}" task could not be initialized with its input parameters. {1} {StrBegin="MSB4063: "} diff --git a/src/Build/Resources/xlf/Strings.cs.xlf b/src/Build/Resources/xlf/Strings.cs.xlf index 8a437b75511..3ab02a754b8 100644 --- a/src/Build/Resources/xlf/Strings.cs.xlf +++ b/src/Build/Resources/xlf/Strings.cs.xlf @@ -926,6 +926,11 @@ Chyby: {3} MSB4181: Úloha {0} vrátila false, ale do protokolu se nezaznamenala chyba. {StrBegin="MSB4181: "} + + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {0}{1} test {2} ({3}s) {0}{1} – test {2} ({3} s) diff --git a/src/Build/Resources/xlf/Strings.de.xlf b/src/Build/Resources/xlf/Strings.de.xlf index 0a8f7dc1ea8..8229f6750e9 100644 --- a/src/Build/Resources/xlf/Strings.de.xlf +++ b/src/Build/Resources/xlf/Strings.de.xlf @@ -926,6 +926,11 @@ Fehler: {3} MSB4181: Die Aufgabe "{0}" hat FALSE zurückgegeben, jedoch keinen Fehler protokolliert. {StrBegin="MSB4181: "} + + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {0}{1} test {2} ({3}s) {0}{1} Test {2} ({3}s) diff --git a/src/Build/Resources/xlf/Strings.es.xlf b/src/Build/Resources/xlf/Strings.es.xlf index b9d175655d3..52e64d06717 100644 --- a/src/Build/Resources/xlf/Strings.es.xlf +++ b/src/Build/Resources/xlf/Strings.es.xlf @@ -926,6 +926,11 @@ Errores: {3} MSB4181: La tarea "{0}" devolvió false, pero no registró un error. {StrBegin="MSB4181: "} + + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {0}{1} test {2} ({3}s) {0}{1} prueba{2} ({3}s) diff --git a/src/Build/Resources/xlf/Strings.fr.xlf b/src/Build/Resources/xlf/Strings.fr.xlf index cc2530e3f00..dd9e944f2f7 100644 --- a/src/Build/Resources/xlf/Strings.fr.xlf +++ b/src/Build/Resources/xlf/Strings.fr.xlf @@ -926,6 +926,11 @@ Erreurs : {3} MSB4181: la tâche "{0}" a retourné false mais n'a pas journalisé d'erreur. {StrBegin="MSB4181: "} + + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {0}{1} test {2} ({3}s) {0}Test de {1} : {2} ({3} s) diff --git a/src/Build/Resources/xlf/Strings.it.xlf b/src/Build/Resources/xlf/Strings.it.xlf index e3f4dcc4d19..7e25f74bcb6 100644 --- a/src/Build/Resources/xlf/Strings.it.xlf +++ b/src/Build/Resources/xlf/Strings.it.xlf @@ -926,6 +926,11 @@ Errori: {3} MSB4181: l'attività "{0}" ha restituito false, ma non è stato registrato alcun errore. {StrBegin="MSB4181: "} + + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {0}{1} test {2} ({3}s) {0}{1} test {2} {3} diff --git a/src/Build/Resources/xlf/Strings.ja.xlf b/src/Build/Resources/xlf/Strings.ja.xlf index 0049e58c17d..44012caaddc 100644 --- a/src/Build/Resources/xlf/Strings.ja.xlf +++ b/src/Build/Resources/xlf/Strings.ja.xlf @@ -926,6 +926,11 @@ Errors: {3} MSB4181: "{0}" タスクから false が返されましたが、エラーがログに記録されませんでした。 {StrBegin="MSB4181: "} + + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {0}{1} test {2} ({3}s) {0}{1} テスト {2} ({3} 秒) diff --git a/src/Build/Resources/xlf/Strings.ko.xlf b/src/Build/Resources/xlf/Strings.ko.xlf index 4e854a096e3..554ba6afe88 100644 --- a/src/Build/Resources/xlf/Strings.ko.xlf +++ b/src/Build/Resources/xlf/Strings.ko.xlf @@ -926,6 +926,11 @@ Errors: {3} MSB4181: "{0}" 작업이 false를 반환했지만 오류를 기록하지 않았습니다. {StrBegin="MSB4181: "} + + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {0}{1} test {2} ({3}s) {0}{1} 테스트 {2}({3}초) diff --git a/src/Build/Resources/xlf/Strings.pl.xlf b/src/Build/Resources/xlf/Strings.pl.xlf index a6bc2289903..4974fdc22d0 100644 --- a/src/Build/Resources/xlf/Strings.pl.xlf +++ b/src/Build/Resources/xlf/Strings.pl.xlf @@ -926,6 +926,11 @@ Błędy: {3} MSB4181: Zadanie „{0}” zwróciło wartość false, ale nie zarejestrowało błędu. {StrBegin="MSB4181: "} + + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {0}{1} test {2} ({3}s) {0}{1} test {2} ({3}s) diff --git a/src/Build/Resources/xlf/Strings.pt-BR.xlf b/src/Build/Resources/xlf/Strings.pt-BR.xlf index 4bb69ae2752..6fb990b047b 100644 --- a/src/Build/Resources/xlf/Strings.pt-BR.xlf +++ b/src/Build/Resources/xlf/Strings.pt-BR.xlf @@ -926,6 +926,11 @@ Erros: {3} MSB4181: A tarefa "{0}" retornou false, mas não registrou um erro. {StrBegin="MSB4181: "} + + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {0}{1} test {2} ({3}s) {0}{1} teste {2} ({3}s) diff --git a/src/Build/Resources/xlf/Strings.ru.xlf b/src/Build/Resources/xlf/Strings.ru.xlf index 78d728ca654..967e342fef6 100644 --- a/src/Build/Resources/xlf/Strings.ru.xlf +++ b/src/Build/Resources/xlf/Strings.ru.xlf @@ -926,6 +926,11 @@ Errors: {3} MSB4181: задача "{0}" возвратила значение false, но не зарегистрировала ошибку. {StrBegin="MSB4181: "} + + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {0}{1} test {2} ({3}s) {0}{1} (тест) {2} ({3} с) diff --git a/src/Build/Resources/xlf/Strings.tr.xlf b/src/Build/Resources/xlf/Strings.tr.xlf index b93685a4a56..9ad0b82d30f 100644 --- a/src/Build/Resources/xlf/Strings.tr.xlf +++ b/src/Build/Resources/xlf/Strings.tr.xlf @@ -926,6 +926,11 @@ Hatalar: {3} MSB4181: "{0}" görevi false değerini döndürdü ancak günlüğe hata kaydetmedi. {StrBegin="MSB4181: "} + + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {0}{1} test {2} ({3}s) {0}{1} testi {2} ({3}s) diff --git a/src/Build/Resources/xlf/Strings.zh-Hans.xlf b/src/Build/Resources/xlf/Strings.zh-Hans.xlf index 1b74008c385..66f200f5d99 100644 --- a/src/Build/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/Build/Resources/xlf/Strings.zh-Hans.xlf @@ -926,6 +926,11 @@ Errors: {3} MSB4181: “{0}”任务返回了 false,但未记录错误。 {StrBegin="MSB4181: "} + + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {0}{1} test {2} ({3}s) {0}{1} 测试 {2} ({3} 秒) diff --git a/src/Build/Resources/xlf/Strings.zh-Hant.xlf b/src/Build/Resources/xlf/Strings.zh-Hant.xlf index d61942aa686..cbfa3637c01 100644 --- a/src/Build/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/Build/Resources/xlf/Strings.zh-Hant.xlf @@ -926,6 +926,11 @@ Errors: {3} MSB4181: "{0}" 工作傳回了 False,但未記錄錯誤。 {StrBegin="MSB4181: "} + + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {0}{1} test {2} ({3}s) {0}{1} 測試 {2} ({3} 秒) From 1cac0ec070ab73e2ba8973e7b504b8f2c79ac940 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Oct 2025 15:47:23 +0000 Subject: [PATCH 02/15] Add NETFRAMEWORK-only check for .NET runtime tasks and unit tests - Added #if NETFRAMEWORK guard around runtime check in AcquireAndSetUpHost - Created unit tests with WindowsFullFrameworkOnlyFact attribute - Tests verify MSB4233 error is thrown with proper task name and assembly location - Added comments explaining why #if is needed alongside the test attribute Co-authored-by: baronfel <573979+baronfel@users.noreply.github.com> --- .../NodeProviderOutOfProcTaskHost_Tests.cs | 165 ++++++++++++++++++ .../NodeProviderOutOfProcTaskHost.cs | 4 +- 2 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 src/Build.UnitTests/BackEnd/NodeProviderOutOfProcTaskHost_Tests.cs diff --git a/src/Build.UnitTests/BackEnd/NodeProviderOutOfProcTaskHost_Tests.cs b/src/Build.UnitTests/BackEnd/NodeProviderOutOfProcTaskHost_Tests.cs new file mode 100644 index 00000000000..451a662a9e2 --- /dev/null +++ b/src/Build.UnitTests/BackEnd/NodeProviderOutOfProcTaskHost_Tests.cs @@ -0,0 +1,165 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Globalization; +using Microsoft.Build.BackEnd; +using Microsoft.Build.Exceptions; +using Microsoft.Build.Shared; +using Microsoft.Build.UnitTests.BackEnd; +using Shouldly; +using Xunit; +using Xunit.NetCore.Extensions; + +#nullable disable + +namespace Microsoft.Build.Engine.UnitTests.BackEnd +{ + /// + /// Tests for NodeProviderOutOfProcTaskHost, specifically error handling for unsupported runtime options. + /// + public class NodeProviderOutOfProcTaskHost_Tests : IDisposable + { + private IBuildComponent _nodeProviderComponent; + private NodeProviderOutOfProcTaskHost _nodeProvider; + private MockHost _mockHost; + + public NodeProviderOutOfProcTaskHost_Tests() + { + _mockHost = new MockHost(); + _nodeProviderComponent = NodeProviderOutOfProcTaskHost.CreateComponent(BuildComponentType.OutOfProcTaskHostNodeProvider); + _nodeProvider = _nodeProviderComponent as NodeProviderOutOfProcTaskHost; + _nodeProvider.InitializeComponent(_mockHost); + } + + public void Dispose() + { + _nodeProvider?.ShutdownComponent(); + _mockHost = null; + _nodeProvider = null; + _nodeProviderComponent = null; + } + + /// + /// Verify that attempting to acquire a task host with the .NET runtime flag throws InvalidProjectFileException + /// with the MSB4233 error code and includes the task name and assembly location. + /// This should only happen on .NET Framework builds of MSBuild. + /// + [WindowsFullFrameworkOnlyFact] + public void AcquireAndSetUpHost_WithNETRuntime_ThrowsInvalidProjectFileException() + { + // This test uses HandshakeOptions which is internal to Microsoft.Build and only accessible + // from test projects on NETFRAMEWORK builds due to InternalsVisibleTo. The WindowsFullFrameworkOnlyFact + // attribute skips test execution on non-Framework builds, but we also need the #if to skip compilation. +#if NETFRAMEWORK + // Arrange + HandshakeOptions hostContext = HandshakeOptions.TaskHost | HandshakeOptions.NET | HandshakeOptions.X64; + string taskName = "MyNetTask"; + string taskLocation = "C:\\Path\\To\\MyTask.dll"; + string projectFile = "C:\\Project\\test.proj"; + int lineNumber = 42; + int columnNumber = 10; + + TaskHostConfiguration configuration = new TaskHostConfiguration( + nodeId: 1, + startupDirectory: Environment.CurrentDirectory, + buildProcessEnvironment: new Dictionary(), + culture: CultureInfo.CurrentCulture, + uiCulture: CultureInfo.CurrentUICulture, +#if FEATURE_APPDOMAIN + appDomainSetup: null, +#endif + lineNumberOfTask: lineNumber, + columnNumberOfTask: columnNumber, + projectFileOfTask: projectFile, + continueOnError: false, + taskName: taskName, + taskLocation: taskLocation, + isTaskInputLoggingEnabled: false, + taskParameters: null, + globalParameters: new Dictionary(), + warningsAsErrors: null, + warningsNotAsErrors: null, + warningsAsMessages: null); + + // Act & Assert + InvalidProjectFileException exception = Should.Throw(() => + { + _nodeProvider.AcquireAndSetUpHost(hostContext, null, null, configuration); + }); + + // Verify the exception contains the expected information + exception.ProjectFile.ShouldBe(projectFile); + exception.LineNumber.ShouldBe(lineNumber); + exception.ColumnNumber.ShouldBe(columnNumber); + exception.ErrorCode.ShouldBe("MSB4233"); + exception.Message.ShouldContain(taskName); + exception.Message.ShouldContain(taskLocation); + exception.Message.ShouldContain(".NET"); + exception.Message.ShouldContain("MSBuild 18.0"); + exception.Message.ShouldContain("Visual Studio 2026"); +#endif + } + + /// + /// Verify that acquiring a task host with CLR4 runtime (without NET flag) does not throw the MSB4233 error. + /// Note: This test may fail if the task host cannot actually be launched, but that's expected + /// in this environment. The important part is that it doesn't throw the MSB4233 error. + /// + [WindowsFullFrameworkOnlyFact] + public void AcquireAndSetUpHost_WithoutNETRuntime_DoesNotThrowMSB4233() + { + // This test uses HandshakeOptions which is internal to Microsoft.Build and only accessible + // from test projects on NETFRAMEWORK builds due to InternalsVisibleTo. The WindowsFullFrameworkOnlyFact + // attribute skips test execution on non-Framework builds, but we also need the #if to skip compilation. +#if NETFRAMEWORK + // Arrange + HandshakeOptions hostContext = HandshakeOptions.TaskHost | HandshakeOptions.X64; // CLR4, no NET flag + string taskName = "MyClr4Task"; + string taskLocation = "C:\\Path\\To\\MyTask.dll"; + string projectFile = "C:\\Project\\test.proj"; + + TaskHostConfiguration configuration = new TaskHostConfiguration( + nodeId: 1, + startupDirectory: Environment.CurrentDirectory, + buildProcessEnvironment: new Dictionary(), + culture: CultureInfo.CurrentCulture, + uiCulture: CultureInfo.CurrentUICulture, +#if FEATURE_APPDOMAIN + appDomainSetup: null, +#endif + lineNumberOfTask: 1, + columnNumberOfTask: 1, + projectFileOfTask: projectFile, + continueOnError: false, + taskName: taskName, + taskLocation: taskLocation, + isTaskInputLoggingEnabled: false, + taskParameters: null, + globalParameters: new Dictionary(), + warningsAsErrors: null, + warningsNotAsErrors: null, + warningsAsMessages: null); + + // Act & Assert + // We expect this to either succeed or fail with a different error (like node launch failure), + // but NOT with MSB4233 + try + { + _nodeProvider.AcquireAndSetUpHost(hostContext, null, null, configuration); + // If it succeeds (unlikely in test environment), that's fine + } + catch (InvalidProjectFileException ex) + { + // If it throws InvalidProjectFileException, it should NOT be MSB4233 + ex.ErrorCode.ShouldNotBe("MSB4233", $"Expected error other than MSB4233, but got: {ex.Message}"); + } + catch (Exception) + { + // Other exceptions are fine for this test - we're only checking that MSB4233 isn't thrown + } +#endif + } + } +} diff --git a/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs b/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs index a9e16005e78..dede783145d 100644 --- a/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs +++ b/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs @@ -486,7 +486,8 @@ internal static string GetMSBuildLocationFromHostContext(HandshakeOptions hostCo /// internal bool AcquireAndSetUpHost(HandshakeOptions hostContext, INodePacketFactory factory, INodePacketHandler handler, TaskHostConfiguration configuration) { - // Check if .NET runtime is requested, which is not supported in this version +#if NETFRAMEWORK + // Check if .NET runtime is requested, which is not supported in .NET Framework version of MSBuild if ((hostContext & HandshakeOptions.NET) == HandshakeOptions.NET) { throw new Exceptions.InvalidProjectFileException( @@ -500,6 +501,7 @@ internal bool AcquireAndSetUpHost(HandshakeOptions hostContext, INodePacketFacto null, null); } +#endif bool nodeCreationSucceeded; if (!_nodeContexts.ContainsKey(hostContext)) From 6466abb478b3f521471c6e61d26b8414a456cfd6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Oct 2025 15:49:50 +0000 Subject: [PATCH 03/15] Improve comment explaining why NETFRAMEWORK check is needed - Added MSB4233 error code reference in comment - Clarified that .NET Core/5+ MSBuild (18.0+) supports .NET runtime tasks - Explained that this prevents confusing "MSBuild.dll not found" error Co-authored-by: baronfel <573979+baronfel@users.noreply.github.com> --- .../Communications/NodeProviderOutOfProcTaskHost.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs b/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs index dede783145d..678fa77cb03 100644 --- a/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs +++ b/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs @@ -487,7 +487,9 @@ internal static string GetMSBuildLocationFromHostContext(HandshakeOptions hostCo internal bool AcquireAndSetUpHost(HandshakeOptions hostContext, INodePacketFactory factory, INodePacketHandler handler, TaskHostConfiguration configuration) { #if NETFRAMEWORK - // Check if .NET runtime is requested, which is not supported in .NET Framework version of MSBuild + // MSB4233: Check if .NET runtime is requested, which is not supported in .NET Framework builds of MSBuild (17.14 and earlier). + // .NET Core/5+ builds of MSBuild (18.0+) do support .NET runtime tasks, so this check is not needed there. + // This provides a clear error message instead of the confusing "MSBuild.dll not found" error that would otherwise occur. if ((hostContext & HandshakeOptions.NET) == HandshakeOptions.NET) { throw new Exceptions.InvalidProjectFileException( From 0fdab346ecea8aabcdf161549f4453302cceb1de Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Oct 2025 16:03:48 +0000 Subject: [PATCH 04/15] Address code review feedback - Simplify test assertions to only check error code, task name, and task location - Use ProjectFileErrorUtilities.ThrowInvalidProjectFile helper instead of direct exception throw - Add Locked syntax for .NET, MSBuild, and Visual Studio 2026 in resource string Co-authored-by: baronfel <573979+baronfel@users.noreply.github.com> --- .../NodeProviderOutOfProcTaskHost_Tests.cs | 8 +------- .../NodeProviderOutOfProcTaskHost.cs | 15 +++++---------- src/Build/Resources/Strings.resx | 2 +- src/Build/Resources/xlf/Strings.cs.xlf | 2 +- src/Build/Resources/xlf/Strings.de.xlf | 2 +- src/Build/Resources/xlf/Strings.es.xlf | 2 +- src/Build/Resources/xlf/Strings.fr.xlf | 2 +- src/Build/Resources/xlf/Strings.it.xlf | 2 +- src/Build/Resources/xlf/Strings.ja.xlf | 2 +- src/Build/Resources/xlf/Strings.ko.xlf | 2 +- src/Build/Resources/xlf/Strings.pl.xlf | 2 +- src/Build/Resources/xlf/Strings.pt-BR.xlf | 2 +- src/Build/Resources/xlf/Strings.ru.xlf | 2 +- src/Build/Resources/xlf/Strings.tr.xlf | 2 +- src/Build/Resources/xlf/Strings.zh-Hans.xlf | 2 +- src/Build/Resources/xlf/Strings.zh-Hant.xlf | 2 +- 16 files changed, 20 insertions(+), 31 deletions(-) diff --git a/src/Build.UnitTests/BackEnd/NodeProviderOutOfProcTaskHost_Tests.cs b/src/Build.UnitTests/BackEnd/NodeProviderOutOfProcTaskHost_Tests.cs index 451a662a9e2..ffe8dbe6764 100644 --- a/src/Build.UnitTests/BackEnd/NodeProviderOutOfProcTaskHost_Tests.cs +++ b/src/Build.UnitTests/BackEnd/NodeProviderOutOfProcTaskHost_Tests.cs @@ -89,16 +89,10 @@ public void AcquireAndSetUpHost_WithNETRuntime_ThrowsInvalidProjectFileException _nodeProvider.AcquireAndSetUpHost(hostContext, null, null, configuration); }); - // Verify the exception contains the expected information - exception.ProjectFile.ShouldBe(projectFile); - exception.LineNumber.ShouldBe(lineNumber); - exception.ColumnNumber.ShouldBe(columnNumber); + // Verify the exception contains the expected information (error code, task name, and task location are the important parts) exception.ErrorCode.ShouldBe("MSB4233"); exception.Message.ShouldContain(taskName); exception.Message.ShouldContain(taskLocation); - exception.Message.ShouldContain(".NET"); - exception.Message.ShouldContain("MSBuild 18.0"); - exception.Message.ShouldContain("Visual Studio 2026"); #endif } diff --git a/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs b/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs index 678fa77cb03..0a425fe2118 100644 --- a/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs +++ b/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs @@ -492,16 +492,11 @@ internal bool AcquireAndSetUpHost(HandshakeOptions hostContext, INodePacketFacto // This provides a clear error message instead of the confusing "MSBuild.dll not found" error that would otherwise occur. if ((hostContext & HandshakeOptions.NET) == HandshakeOptions.NET) { - throw new Exceptions.InvalidProjectFileException( - configuration.ProjectFileOfTask, - configuration.LineNumberOfTask, - configuration.ColumnNumberOfTask, - 0, - 0, - ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("TaskRuntimeNET", configuration.TaskName, configuration.TaskLocation), - null, - null, - null); + ProjectFileErrorUtilities.ThrowInvalidProjectFile( + new BuildEventFileInfo(configuration.ProjectFileOfTask, configuration.LineNumberOfTask, configuration.ColumnNumberOfTask), + "TaskRuntimeNET", + configuration.TaskName, + configuration.TaskLocation); } #endif diff --git a/src/Build/Resources/Strings.resx b/src/Build/Resources/Strings.resx index 9137320262c..0b93b94b491 100644 --- a/src/Build/Resources/Strings.resx +++ b/src/Build/Resources/Strings.resx @@ -1240,7 +1240,7 @@ 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. MSB4063: The "{0}" task could not be initialized with its input parameters. {1} diff --git a/src/Build/Resources/xlf/Strings.cs.xlf b/src/Build/Resources/xlf/Strings.cs.xlf index 3ab02a754b8..275dfcfe2f5 100644 --- a/src/Build/Resources/xlf/Strings.cs.xlf +++ b/src/Build/Resources/xlf/Strings.cs.xlf @@ -929,7 +929,7 @@ Chyby: {3} 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. {0}{1} test {2} ({3}s) diff --git a/src/Build/Resources/xlf/Strings.de.xlf b/src/Build/Resources/xlf/Strings.de.xlf index 8229f6750e9..85392a9258a 100644 --- a/src/Build/Resources/xlf/Strings.de.xlf +++ b/src/Build/Resources/xlf/Strings.de.xlf @@ -929,7 +929,7 @@ Fehler: {3} 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. {0}{1} test {2} ({3}s) diff --git a/src/Build/Resources/xlf/Strings.es.xlf b/src/Build/Resources/xlf/Strings.es.xlf index 52e64d06717..6d48bb4e502 100644 --- a/src/Build/Resources/xlf/Strings.es.xlf +++ b/src/Build/Resources/xlf/Strings.es.xlf @@ -929,7 +929,7 @@ Errores: {3} 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. {0}{1} test {2} ({3}s) diff --git a/src/Build/Resources/xlf/Strings.fr.xlf b/src/Build/Resources/xlf/Strings.fr.xlf index dd9e944f2f7..5ab8e033294 100644 --- a/src/Build/Resources/xlf/Strings.fr.xlf +++ b/src/Build/Resources/xlf/Strings.fr.xlf @@ -929,7 +929,7 @@ Erreurs : {3} 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. {0}{1} test {2} ({3}s) diff --git a/src/Build/Resources/xlf/Strings.it.xlf b/src/Build/Resources/xlf/Strings.it.xlf index 7e25f74bcb6..ebd94fc992b 100644 --- a/src/Build/Resources/xlf/Strings.it.xlf +++ b/src/Build/Resources/xlf/Strings.it.xlf @@ -929,7 +929,7 @@ Errori: {3} 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. {0}{1} test {2} ({3}s) diff --git a/src/Build/Resources/xlf/Strings.ja.xlf b/src/Build/Resources/xlf/Strings.ja.xlf index 44012caaddc..70a5e057442 100644 --- a/src/Build/Resources/xlf/Strings.ja.xlf +++ b/src/Build/Resources/xlf/Strings.ja.xlf @@ -929,7 +929,7 @@ Errors: {3} 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. {0}{1} test {2} ({3}s) diff --git a/src/Build/Resources/xlf/Strings.ko.xlf b/src/Build/Resources/xlf/Strings.ko.xlf index 554ba6afe88..dc0409567df 100644 --- a/src/Build/Resources/xlf/Strings.ko.xlf +++ b/src/Build/Resources/xlf/Strings.ko.xlf @@ -929,7 +929,7 @@ Errors: {3} 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. {0}{1} test {2} ({3}s) diff --git a/src/Build/Resources/xlf/Strings.pl.xlf b/src/Build/Resources/xlf/Strings.pl.xlf index 4974fdc22d0..36e010ea2df 100644 --- a/src/Build/Resources/xlf/Strings.pl.xlf +++ b/src/Build/Resources/xlf/Strings.pl.xlf @@ -929,7 +929,7 @@ Błędy: {3} 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. {0}{1} test {2} ({3}s) diff --git a/src/Build/Resources/xlf/Strings.pt-BR.xlf b/src/Build/Resources/xlf/Strings.pt-BR.xlf index 6fb990b047b..c8c318fee4d 100644 --- a/src/Build/Resources/xlf/Strings.pt-BR.xlf +++ b/src/Build/Resources/xlf/Strings.pt-BR.xlf @@ -929,7 +929,7 @@ Erros: {3} 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. {0}{1} test {2} ({3}s) diff --git a/src/Build/Resources/xlf/Strings.ru.xlf b/src/Build/Resources/xlf/Strings.ru.xlf index 967e342fef6..e60aa1dbc92 100644 --- a/src/Build/Resources/xlf/Strings.ru.xlf +++ b/src/Build/Resources/xlf/Strings.ru.xlf @@ -929,7 +929,7 @@ Errors: {3} 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. {0}{1} test {2} ({3}s) diff --git a/src/Build/Resources/xlf/Strings.tr.xlf b/src/Build/Resources/xlf/Strings.tr.xlf index 9ad0b82d30f..a9455173c69 100644 --- a/src/Build/Resources/xlf/Strings.tr.xlf +++ b/src/Build/Resources/xlf/Strings.tr.xlf @@ -929,7 +929,7 @@ Hatalar: {3} 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. {0}{1} test {2} ({3}s) diff --git a/src/Build/Resources/xlf/Strings.zh-Hans.xlf b/src/Build/Resources/xlf/Strings.zh-Hans.xlf index 66f200f5d99..5ff8d3b4a3d 100644 --- a/src/Build/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/Build/Resources/xlf/Strings.zh-Hans.xlf @@ -929,7 +929,7 @@ Errors: {3} 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. {0}{1} test {2} ({3}s) diff --git a/src/Build/Resources/xlf/Strings.zh-Hant.xlf b/src/Build/Resources/xlf/Strings.zh-Hant.xlf index cbfa3637c01..d7424b1ace9 100644 --- a/src/Build/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/Build/Resources/xlf/Strings.zh-Hant.xlf @@ -929,7 +929,7 @@ Errors: {3} 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - {StrBegin="MSB4233: "}LOCALIZATION: .NET should not be localized. + {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. {0}{1} test {2} ({3}s) From fe07879e66a2d9f4b04a7a52fa1c917ac7bbba00 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Oct 2025 16:15:20 +0000 Subject: [PATCH 05/15] Add end-to-end tests for .NET runtime task error handling - Add BuildManager API tests in DotNetRuntimeTask_EndToEnd_Tests.cs - Add MSBuild CLI tests in DotNetRuntimeTask_CLI_Tests.cs - Tests verify MSB4233 error is shown with clear message - Tests use WindowsFullFrameworkOnlyFact since feature is Framework-only - Tests follow existing patterns and will run in CI on Windows Co-authored-by: baronfel <573979+baronfel@users.noreply.github.com> --- .../DotNetRuntimeTask_EndToEnd_Tests.cs | 149 ++++++++++++++++++ .../DotNetRuntimeTask_CLI_Tests.cs | 146 +++++++++++++++++ 2 files changed, 295 insertions(+) create mode 100644 src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs create mode 100644 src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs diff --git a/src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs b/src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs new file mode 100644 index 00000000000..f2de0e0f67c --- /dev/null +++ b/src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs @@ -0,0 +1,149 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Build.Evaluation; +using Microsoft.Build.Execution; +using Microsoft.Build.Framework; +using Microsoft.Build.UnitTests; +using Shouldly; +using Xunit; +using Xunit.Abstractions; +using Xunit.NetCore.Extensions; + +#nullable disable + +namespace Microsoft.Build.Engine.UnitTests.BackEnd +{ + /// + /// End-to-end tests for .NET Runtime task error handling. + /// These tests verify that MSBuild 17.14 gives a clear error when attempting to use Runtime="NET" tasks. + /// + public class DotNetRuntimeTask_EndToEnd_Tests + { + private readonly ITestOutputHelper _output; + + public DotNetRuntimeTask_EndToEnd_Tests(ITestOutputHelper output) + { + _output = output; + } + + /// + /// Test that BuildManager API gives clear error (MSB4233) when attempting to build a project + /// that uses a task with Runtime="NET". + /// + [WindowsFullFrameworkOnlyFact] + public void BuildManager_WithDotNetRuntimeTask_ShowsClearError() + { + // This test uses a real task but specifies Runtime="NET" which is not supported on .NET Framework builds. + // We expect the build to fail with MSB4233 error that clearly explains the issue. +#if NETFRAMEWORK + string projectContent = @" + + + + + + + +"; + + using (var env = TestEnvironment.Create(_output)) + { + var testProject = env.CreateTestProjectWithFiles(projectContent); + var logger = new MockLogger(_output); + + var parameters = new BuildParameters + { + Loggers = new[] { logger } + }; + + var result = Helpers.BuildProjectFileUsingBuildManager(testProject.ProjectFile, logger, parameters, targetsToBuild: new[] { "TestTask" }); + + // Build should fail + result.OverallResult.ShouldBe(BuildResultCode.Failure); + + // Should log MSB4233 error + logger.ErrorCount.ShouldBeGreaterThan(0); + logger.Errors[0].Code.ShouldBe("MSB4233"); + + // Error message should contain the task name and indicate .NET runtime is not supported + logger.Errors[0].Message.ShouldContain("ProcessIdTask"); + logger.Errors[0].Message.ShouldContain(".NET runtime"); + logger.Errors[0].Message.ShouldContain("MSBuild 18.0"); + } +#endif + } + + /// + /// Test that a project can successfully use a task without Runtime="NET" specified. + /// This verifies we didn't break normal task execution. + /// + [Fact] + public void BuildManager_WithoutDotNetRuntime_Succeeds() + { + string projectContent = @" + + + + + + + +"; + + using (var env = TestEnvironment.Create(_output)) + { + var testProject = env.CreateTestProjectWithFiles(projectContent); + var logger = new MockLogger(_output); + + var result = Helpers.BuildProjectFileUsingBuildManager(testProject.ProjectFile, logger, targetsToBuild: new[] { "TestTask" }); + + // Build should succeed + result.OverallResult.ShouldBe(BuildResultCode.Success); + + // Should not log MSB4233 error + logger.Errors.ShouldNotContain(e => e.Code == "MSB4233"); + } + } + + /// + /// Test that using ProjectInstance.Build() with a task that has Runtime="NET" gives clear error. + /// This is another common API pattern users might use. + /// + [WindowsFullFrameworkOnlyFact] + public void ProjectInstance_WithDotNetRuntimeTask_ShowsClearError() + { +#if NETFRAMEWORK + string projectContent = @" + + + + + + + +"; + + using (var env = TestEnvironment.Create(_output)) + { + var testProject = env.CreateTestProjectWithFiles(projectContent); + var logger = new MockLogger(_output); + + var projectInstance = new ProjectInstance(testProject.ProjectFile); + var buildResult = projectInstance.Build(targets: new[] { "TestTask" }, loggers: new[] { logger }); + + // Build should fail + buildResult.ShouldBeFalse(); + + // Should log MSB4233 error + logger.ErrorCount.ShouldBeGreaterThan(0); + logger.Errors[0].Code.ShouldBe("MSB4233"); + + // Error message should contain task name + logger.Errors[0].Message.ShouldContain("ProcessIdTask"); + logger.Errors[0].Message.ShouldContain(".NET runtime"); + } +#endif + } + } +} diff --git a/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs b/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs new file mode 100644 index 00000000000..435f2c83a5c --- /dev/null +++ b/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs @@ -0,0 +1,146 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; +using Microsoft.Build.UnitTests.Shared; +using Shouldly; +using Xunit; +using Xunit.Abstractions; +using Xunit.NetCore.Extensions; + +#nullable disable + +namespace Microsoft.Build.UnitTests +{ + /// + /// End-to-end MSBuild CLI tests for .NET Runtime task error handling. + /// These tests verify that MSBuild.exe CLI gives a clear error when attempting to use Runtime="NET" tasks. + /// + public class DotNetRuntimeTask_CLI_Tests + { + private readonly ITestOutputHelper _output; + + public DotNetRuntimeTask_CLI_Tests(ITestOutputHelper output) + { + _output = output; + } + + /// + /// Test that MSBuild.exe CLI gives clear error (MSB4233) when building a project + /// that uses a task with Runtime="NET". + /// + [WindowsFullFrameworkOnlyFact] + public void MSBuildCLI_WithDotNetRuntimeTask_ShowsClearError() + { + // This test verifies that running MSBuild.exe from command line with a project that uses Runtime="NET" + // produces a clear error message rather than a confusing "MSBuild.dll not found" error. +#if NETFRAMEWORK + using (var env = TestEnvironment.Create(_output)) + { + // Create a simple .NET task DLL content for testing + string taskAssemblyContent = @" +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace TestTasks +{ + public class SimpleTask : Task + { + public override bool Execute() + { + Log.LogMessage(MessageImportance.High, ""SimpleTask executed""); + return true; + } + } +}"; + + // Create the task assembly project + string taskProjectContent = @" + + + net472 + + + + + +"; + + var taskProjectFile = env.CreateFile("SimpleTask.csproj", taskProjectContent).Path; + var taskSourceFile = env.CreateFile("SimpleTask.cs", taskAssemblyContent).Path; + + // Build the task assembly (this should succeed) + string buildTaskOutput = RunnerUtilities.ExecMSBuild($"\"{taskProjectFile}\" /t:Build /v:m", out bool taskBuildSuccess); + + // If task build fails, skip the test as it's an environment issue, not what we're testing + if (!taskBuildSuccess) + { + _output.WriteLine("Warning: Could not build test task assembly. Skipping test."); + _output.WriteLine(buildTaskOutput); + return; + } + + string taskAssemblyPath = Path.Combine(Path.GetDirectoryName(taskProjectFile), "bin", "Debug", "net472", "SimpleTask.dll"); + + // Now create a project that uses the task with Runtime="NET" + string projectContent = $@" + + + + + +"; + + var projectFile = env.CreateFile("test.proj", projectContent).Path; + + // Execute MSBuild on the project - should fail with MSB4233 + string output = RunnerUtilities.ExecMSBuild($"\"{projectFile}\" /t:TestTarget", out bool success, _output); + + // Build should fail + success.ShouldBeFalse(); + + // Output should contain MSB4233 error + output.ShouldContain("MSB4233"); + + // Output should contain clear error message about .NET runtime not being supported + output.ShouldContain("SimpleTask"); + output.ShouldContain(".NET runtime"); + output.ShouldContain("MSBuild 18.0"); + } +#endif + } + + /// + /// Test that MSBuild.exe can successfully build a project with a task without Runtime="NET". + /// This verifies we didn't break normal CLI execution. + /// + [WindowsOnlyFact] + public void MSBuildCLI_WithoutDotNetRuntime_Succeeds() + { + using (var env = TestEnvironment.Create(_output)) + { + // Create a simple project that uses a built-in task + string projectContent = @" + + + + +"; + + var projectFile = env.CreateFile("test.proj", projectContent).Path; + + // Execute MSBuild on the project - should succeed + string output = RunnerUtilities.ExecMSBuild($"\"{projectFile}\" /t:TestTarget", out bool success, _output); + + // Build should succeed + success.ShouldBeTrue(); + + // Output should not contain MSB4233 error + output.ShouldNotContain("MSB4233"); + + // Should see our message + output.ShouldContain("Hello from MSBuild"); + } + } + } +} From edb44a578c8599b8787b08b88839d69a307426e5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Oct 2025 20:26:15 +0000 Subject: [PATCH 06/15] Remove NodeProviderOutOfProcTaskHost_Tests that use HandshakeOptions The unit tests in NodeProviderOutOfProcTaskHost_Tests.cs directly used the internal HandshakeOptions type, which caused compilation issues in multi-targeting scenarios. The end-to-end tests in DotNetRuntimeTask_EndToEnd_Tests.cs and DotNetRuntimeTask_CLI_Tests.cs provide sufficient coverage for the MSB4233 error handling without requiring direct access to internal types. Co-authored-by: baronfel <573979+baronfel@users.noreply.github.com> --- .../NodeProviderOutOfProcTaskHost_Tests.cs | 159 ------------------ 1 file changed, 159 deletions(-) delete mode 100644 src/Build.UnitTests/BackEnd/NodeProviderOutOfProcTaskHost_Tests.cs diff --git a/src/Build.UnitTests/BackEnd/NodeProviderOutOfProcTaskHost_Tests.cs b/src/Build.UnitTests/BackEnd/NodeProviderOutOfProcTaskHost_Tests.cs deleted file mode 100644 index ffe8dbe6764..00000000000 --- a/src/Build.UnitTests/BackEnd/NodeProviderOutOfProcTaskHost_Tests.cs +++ /dev/null @@ -1,159 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.Globalization; -using Microsoft.Build.BackEnd; -using Microsoft.Build.Exceptions; -using Microsoft.Build.Shared; -using Microsoft.Build.UnitTests.BackEnd; -using Shouldly; -using Xunit; -using Xunit.NetCore.Extensions; - -#nullable disable - -namespace Microsoft.Build.Engine.UnitTests.BackEnd -{ - /// - /// Tests for NodeProviderOutOfProcTaskHost, specifically error handling for unsupported runtime options. - /// - public class NodeProviderOutOfProcTaskHost_Tests : IDisposable - { - private IBuildComponent _nodeProviderComponent; - private NodeProviderOutOfProcTaskHost _nodeProvider; - private MockHost _mockHost; - - public NodeProviderOutOfProcTaskHost_Tests() - { - _mockHost = new MockHost(); - _nodeProviderComponent = NodeProviderOutOfProcTaskHost.CreateComponent(BuildComponentType.OutOfProcTaskHostNodeProvider); - _nodeProvider = _nodeProviderComponent as NodeProviderOutOfProcTaskHost; - _nodeProvider.InitializeComponent(_mockHost); - } - - public void Dispose() - { - _nodeProvider?.ShutdownComponent(); - _mockHost = null; - _nodeProvider = null; - _nodeProviderComponent = null; - } - - /// - /// Verify that attempting to acquire a task host with the .NET runtime flag throws InvalidProjectFileException - /// with the MSB4233 error code and includes the task name and assembly location. - /// This should only happen on .NET Framework builds of MSBuild. - /// - [WindowsFullFrameworkOnlyFact] - public void AcquireAndSetUpHost_WithNETRuntime_ThrowsInvalidProjectFileException() - { - // This test uses HandshakeOptions which is internal to Microsoft.Build and only accessible - // from test projects on NETFRAMEWORK builds due to InternalsVisibleTo. The WindowsFullFrameworkOnlyFact - // attribute skips test execution on non-Framework builds, but we also need the #if to skip compilation. -#if NETFRAMEWORK - // Arrange - HandshakeOptions hostContext = HandshakeOptions.TaskHost | HandshakeOptions.NET | HandshakeOptions.X64; - string taskName = "MyNetTask"; - string taskLocation = "C:\\Path\\To\\MyTask.dll"; - string projectFile = "C:\\Project\\test.proj"; - int lineNumber = 42; - int columnNumber = 10; - - TaskHostConfiguration configuration = new TaskHostConfiguration( - nodeId: 1, - startupDirectory: Environment.CurrentDirectory, - buildProcessEnvironment: new Dictionary(), - culture: CultureInfo.CurrentCulture, - uiCulture: CultureInfo.CurrentUICulture, -#if FEATURE_APPDOMAIN - appDomainSetup: null, -#endif - lineNumberOfTask: lineNumber, - columnNumberOfTask: columnNumber, - projectFileOfTask: projectFile, - continueOnError: false, - taskName: taskName, - taskLocation: taskLocation, - isTaskInputLoggingEnabled: false, - taskParameters: null, - globalParameters: new Dictionary(), - warningsAsErrors: null, - warningsNotAsErrors: null, - warningsAsMessages: null); - - // Act & Assert - InvalidProjectFileException exception = Should.Throw(() => - { - _nodeProvider.AcquireAndSetUpHost(hostContext, null, null, configuration); - }); - - // Verify the exception contains the expected information (error code, task name, and task location are the important parts) - exception.ErrorCode.ShouldBe("MSB4233"); - exception.Message.ShouldContain(taskName); - exception.Message.ShouldContain(taskLocation); -#endif - } - - /// - /// Verify that acquiring a task host with CLR4 runtime (without NET flag) does not throw the MSB4233 error. - /// Note: This test may fail if the task host cannot actually be launched, but that's expected - /// in this environment. The important part is that it doesn't throw the MSB4233 error. - /// - [WindowsFullFrameworkOnlyFact] - public void AcquireAndSetUpHost_WithoutNETRuntime_DoesNotThrowMSB4233() - { - // This test uses HandshakeOptions which is internal to Microsoft.Build and only accessible - // from test projects on NETFRAMEWORK builds due to InternalsVisibleTo. The WindowsFullFrameworkOnlyFact - // attribute skips test execution on non-Framework builds, but we also need the #if to skip compilation. -#if NETFRAMEWORK - // Arrange - HandshakeOptions hostContext = HandshakeOptions.TaskHost | HandshakeOptions.X64; // CLR4, no NET flag - string taskName = "MyClr4Task"; - string taskLocation = "C:\\Path\\To\\MyTask.dll"; - string projectFile = "C:\\Project\\test.proj"; - - TaskHostConfiguration configuration = new TaskHostConfiguration( - nodeId: 1, - startupDirectory: Environment.CurrentDirectory, - buildProcessEnvironment: new Dictionary(), - culture: CultureInfo.CurrentCulture, - uiCulture: CultureInfo.CurrentUICulture, -#if FEATURE_APPDOMAIN - appDomainSetup: null, -#endif - lineNumberOfTask: 1, - columnNumberOfTask: 1, - projectFileOfTask: projectFile, - continueOnError: false, - taskName: taskName, - taskLocation: taskLocation, - isTaskInputLoggingEnabled: false, - taskParameters: null, - globalParameters: new Dictionary(), - warningsAsErrors: null, - warningsNotAsErrors: null, - warningsAsMessages: null); - - // Act & Assert - // We expect this to either succeed or fail with a different error (like node launch failure), - // but NOT with MSB4233 - try - { - _nodeProvider.AcquireAndSetUpHost(hostContext, null, null, configuration); - // If it succeeds (unlikely in test environment), that's fine - } - catch (InvalidProjectFileException ex) - { - // If it throws InvalidProjectFileException, it should NOT be MSB4233 - ex.ErrorCode.ShouldNotBe("MSB4233", $"Expected error other than MSB4233, but got: {ex.Message}"); - } - catch (Exception) - { - // Other exceptions are fine for this test - we're only checking that MSB4233 isn't thrown - } -#endif - } - } -} From 62db1fbdc5d5680c565f4fddae09d197e15a5ee5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Oct 2025 21:42:59 +0000 Subject: [PATCH 07/15] Make test files nullable-aware Remove #nullable disable directive from DotNetRuntimeTask_EndToEnd_Tests.cs and DotNetRuntimeTask_CLI_Tests.cs to enable nullable reference type checking. Co-authored-by: baronfel <573979+baronfel@users.noreply.github.com> --- src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs | 2 -- src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs b/src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs index f2de0e0f67c..97d51827943 100644 --- a/src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs +++ b/src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs @@ -10,8 +10,6 @@ using Xunit.Abstractions; using Xunit.NetCore.Extensions; -#nullable disable - namespace Microsoft.Build.Engine.UnitTests.BackEnd { /// diff --git a/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs b/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs index 435f2c83a5c..19fe1325aff 100644 --- a/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs +++ b/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs @@ -8,8 +8,6 @@ using Xunit.Abstractions; using Xunit.NetCore.Extensions; -#nullable disable - namespace Microsoft.Build.UnitTests { /// From dc65b512e53f551a4602ae39258fab4cb2c97e49 Mon Sep 17 00:00:00 2001 From: Chet Husk Date: Fri, 17 Oct 2025 17:08:43 -0500 Subject: [PATCH 08/15] Apply suggestions from code review Co-authored-by: Rainer Sigwald --- src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs | 2 +- .../Components/Communications/NodeProviderOutOfProcTaskHost.cs | 2 +- src/Build/Resources/Strings.resx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs b/src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs index 97d51827943..f7604d2231c 100644 --- a/src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs +++ b/src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs @@ -37,7 +37,7 @@ public void BuildManager_WithDotNetRuntimeTask_ShowsClearError() #if NETFRAMEWORK string projectContent = @" - + diff --git a/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs b/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs index 0a425fe2118..213932d2af4 100644 --- a/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs +++ b/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs @@ -488,7 +488,7 @@ internal bool AcquireAndSetUpHost(HandshakeOptions hostContext, INodePacketFacto { #if NETFRAMEWORK // MSB4233: Check if .NET runtime is requested, which is not supported in .NET Framework builds of MSBuild (17.14 and earlier). - // .NET Core/5+ builds of MSBuild (18.0+) do support .NET runtime tasks, so this check is not needed there. + // .NET Core/5+ builds of MSBuild do support .NET runtime tasks, so this check is not needed there. // This provides a clear error message instead of the confusing "MSBuild.dll not found" error that would otherwise occur. if ((hostContext & HandshakeOptions.NET) == HandshakeOptions.NET) { diff --git a/src/Build/Resources/Strings.resx b/src/Build/Resources/Strings.resx index 0b93b94b491..e8062a05cb2 100644 --- a/src/Build/Resources/Strings.resx +++ b/src/Build/Resources/Strings.resx @@ -1239,7 +1239,7 @@ {StrBegin="MSB4217: "} - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. From fcf4963fe81a41323bcef1fe10f4619b6c341c5e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Oct 2025 22:14:18 +0000 Subject: [PATCH 09/15] Address code review feedback - Update comment in NodeProviderOutOfProcTaskHost.cs to clarify version (18.0+) - Remove redundant tests that don't add value: - BuildManager_WithoutDotNetRuntime_Succeeds - ProjectInstance_WithDotNetRuntimeTask_ShowsClearError - MSBuildCLI_WithoutDotNetRuntime_Succeeds - Keep only the essential test that verifies MSB4233 error for Runtime="NET" tasks Co-authored-by: baronfel <573979+baronfel@users.noreply.github.com> --- .../DotNetRuntimeTask_EndToEnd_Tests.cs | 72 ------------------- .../NodeProviderOutOfProcTaskHost.cs | 2 +- src/Build/Resources/xlf/Strings.cs.xlf | 4 +- src/Build/Resources/xlf/Strings.de.xlf | 4 +- src/Build/Resources/xlf/Strings.es.xlf | 4 +- src/Build/Resources/xlf/Strings.fr.xlf | 4 +- src/Build/Resources/xlf/Strings.it.xlf | 4 +- src/Build/Resources/xlf/Strings.ja.xlf | 4 +- src/Build/Resources/xlf/Strings.ko.xlf | 4 +- src/Build/Resources/xlf/Strings.pl.xlf | 4 +- src/Build/Resources/xlf/Strings.pt-BR.xlf | 4 +- src/Build/Resources/xlf/Strings.ru.xlf | 4 +- src/Build/Resources/xlf/Strings.tr.xlf | 4 +- src/Build/Resources/xlf/Strings.zh-Hans.xlf | 4 +- src/Build/Resources/xlf/Strings.zh-Hant.xlf | 4 +- .../DotNetRuntimeTask_CLI_Tests.cs | 33 --------- 16 files changed, 27 insertions(+), 132 deletions(-) diff --git a/src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs b/src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs index f7604d2231c..f6d24d9fe0d 100644 --- a/src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs +++ b/src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs @@ -69,78 +69,6 @@ public void BuildManager_WithDotNetRuntimeTask_ShowsClearError() logger.Errors[0].Message.ShouldContain(".NET runtime"); logger.Errors[0].Message.ShouldContain("MSBuild 18.0"); } -#endif - } - - /// - /// Test that a project can successfully use a task without Runtime="NET" specified. - /// This verifies we didn't break normal task execution. - /// - [Fact] - public void BuildManager_WithoutDotNetRuntime_Succeeds() - { - string projectContent = @" - - - - - - - -"; - - using (var env = TestEnvironment.Create(_output)) - { - var testProject = env.CreateTestProjectWithFiles(projectContent); - var logger = new MockLogger(_output); - - var result = Helpers.BuildProjectFileUsingBuildManager(testProject.ProjectFile, logger, targetsToBuild: new[] { "TestTask" }); - - // Build should succeed - result.OverallResult.ShouldBe(BuildResultCode.Success); - - // Should not log MSB4233 error - logger.Errors.ShouldNotContain(e => e.Code == "MSB4233"); - } - } - - /// - /// Test that using ProjectInstance.Build() with a task that has Runtime="NET" gives clear error. - /// This is another common API pattern users might use. - /// - [WindowsFullFrameworkOnlyFact] - public void ProjectInstance_WithDotNetRuntimeTask_ShowsClearError() - { -#if NETFRAMEWORK - string projectContent = @" - - - - - - - -"; - - using (var env = TestEnvironment.Create(_output)) - { - var testProject = env.CreateTestProjectWithFiles(projectContent); - var logger = new MockLogger(_output); - - var projectInstance = new ProjectInstance(testProject.ProjectFile); - var buildResult = projectInstance.Build(targets: new[] { "TestTask" }, loggers: new[] { logger }); - - // Build should fail - buildResult.ShouldBeFalse(); - - // Should log MSB4233 error - logger.ErrorCount.ShouldBeGreaterThan(0); - logger.Errors[0].Code.ShouldBe("MSB4233"); - - // Error message should contain task name - logger.Errors[0].Message.ShouldContain("ProcessIdTask"); - logger.Errors[0].Message.ShouldContain(".NET runtime"); - } #endif } } diff --git a/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs b/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs index 213932d2af4..0a425fe2118 100644 --- a/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs +++ b/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs @@ -488,7 +488,7 @@ internal bool AcquireAndSetUpHost(HandshakeOptions hostContext, INodePacketFacto { #if NETFRAMEWORK // MSB4233: Check if .NET runtime is requested, which is not supported in .NET Framework builds of MSBuild (17.14 and earlier). - // .NET Core/5+ builds of MSBuild do support .NET runtime tasks, so this check is not needed there. + // .NET Core/5+ builds of MSBuild (18.0+) do support .NET runtime tasks, so this check is not needed there. // This provides a clear error message instead of the confusing "MSBuild.dll not found" error that would otherwise occur. if ((hostContext & HandshakeOptions.NET) == HandshakeOptions.NET) { diff --git a/src/Build/Resources/xlf/Strings.cs.xlf b/src/Build/Resources/xlf/Strings.cs.xlf index 275dfcfe2f5..72edbb3a386 100644 --- a/src/Build/Resources/xlf/Strings.cs.xlf +++ b/src/Build/Resources/xlf/Strings.cs.xlf @@ -927,8 +927,8 @@ Chyby: {3} {StrBegin="MSB4181: "} - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. diff --git a/src/Build/Resources/xlf/Strings.de.xlf b/src/Build/Resources/xlf/Strings.de.xlf index 85392a9258a..1374ca4dbf6 100644 --- a/src/Build/Resources/xlf/Strings.de.xlf +++ b/src/Build/Resources/xlf/Strings.de.xlf @@ -927,8 +927,8 @@ Fehler: {3} {StrBegin="MSB4181: "} - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. diff --git a/src/Build/Resources/xlf/Strings.es.xlf b/src/Build/Resources/xlf/Strings.es.xlf index 6d48bb4e502..639250a5f8a 100644 --- a/src/Build/Resources/xlf/Strings.es.xlf +++ b/src/Build/Resources/xlf/Strings.es.xlf @@ -927,8 +927,8 @@ Errores: {3} {StrBegin="MSB4181: "} - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. diff --git a/src/Build/Resources/xlf/Strings.fr.xlf b/src/Build/Resources/xlf/Strings.fr.xlf index 5ab8e033294..da8662d4a58 100644 --- a/src/Build/Resources/xlf/Strings.fr.xlf +++ b/src/Build/Resources/xlf/Strings.fr.xlf @@ -927,8 +927,8 @@ Erreurs : {3} {StrBegin="MSB4181: "} - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. diff --git a/src/Build/Resources/xlf/Strings.it.xlf b/src/Build/Resources/xlf/Strings.it.xlf index ebd94fc992b..a280d429e0e 100644 --- a/src/Build/Resources/xlf/Strings.it.xlf +++ b/src/Build/Resources/xlf/Strings.it.xlf @@ -927,8 +927,8 @@ Errori: {3} {StrBegin="MSB4181: "} - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. diff --git a/src/Build/Resources/xlf/Strings.ja.xlf b/src/Build/Resources/xlf/Strings.ja.xlf index 70a5e057442..219468f848d 100644 --- a/src/Build/Resources/xlf/Strings.ja.xlf +++ b/src/Build/Resources/xlf/Strings.ja.xlf @@ -927,8 +927,8 @@ Errors: {3} {StrBegin="MSB4181: "} - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. diff --git a/src/Build/Resources/xlf/Strings.ko.xlf b/src/Build/Resources/xlf/Strings.ko.xlf index dc0409567df..ca1a11073ed 100644 --- a/src/Build/Resources/xlf/Strings.ko.xlf +++ b/src/Build/Resources/xlf/Strings.ko.xlf @@ -927,8 +927,8 @@ Errors: {3} {StrBegin="MSB4181: "} - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. diff --git a/src/Build/Resources/xlf/Strings.pl.xlf b/src/Build/Resources/xlf/Strings.pl.xlf index 36e010ea2df..393f026d967 100644 --- a/src/Build/Resources/xlf/Strings.pl.xlf +++ b/src/Build/Resources/xlf/Strings.pl.xlf @@ -927,8 +927,8 @@ Błędy: {3} {StrBegin="MSB4181: "} - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. diff --git a/src/Build/Resources/xlf/Strings.pt-BR.xlf b/src/Build/Resources/xlf/Strings.pt-BR.xlf index c8c318fee4d..3b21d35caa1 100644 --- a/src/Build/Resources/xlf/Strings.pt-BR.xlf +++ b/src/Build/Resources/xlf/Strings.pt-BR.xlf @@ -927,8 +927,8 @@ Erros: {3} {StrBegin="MSB4181: "} - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. diff --git a/src/Build/Resources/xlf/Strings.ru.xlf b/src/Build/Resources/xlf/Strings.ru.xlf index e60aa1dbc92..838d7f72c28 100644 --- a/src/Build/Resources/xlf/Strings.ru.xlf +++ b/src/Build/Resources/xlf/Strings.ru.xlf @@ -927,8 +927,8 @@ Errors: {3} {StrBegin="MSB4181: "} - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. diff --git a/src/Build/Resources/xlf/Strings.tr.xlf b/src/Build/Resources/xlf/Strings.tr.xlf index a9455173c69..b5c0ec0c848 100644 --- a/src/Build/Resources/xlf/Strings.tr.xlf +++ b/src/Build/Resources/xlf/Strings.tr.xlf @@ -927,8 +927,8 @@ Hatalar: {3} {StrBegin="MSB4181: "} - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. diff --git a/src/Build/Resources/xlf/Strings.zh-Hans.xlf b/src/Build/Resources/xlf/Strings.zh-Hans.xlf index 5ff8d3b4a3d..326367317d8 100644 --- a/src/Build/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/Build/Resources/xlf/Strings.zh-Hans.xlf @@ -927,8 +927,8 @@ Errors: {3} {StrBegin="MSB4181: "} - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. diff --git a/src/Build/Resources/xlf/Strings.zh-Hant.xlf b/src/Build/Resources/xlf/Strings.zh-Hant.xlf index d7424b1ace9..948774b29fb 100644 --- a/src/Build/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/Build/Resources/xlf/Strings.zh-Hant.xlf @@ -927,8 +927,8 @@ Errors: {3} {StrBegin="MSB4181: "} - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. - 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 load .NET tasks, MSBuild 18.0 or Visual Studio 2026 must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. + 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, MSBuild 18.0 or Visual Studio 2026 or higher must be used. {StrBegin="MSB4233: "}{Locked=".NET"}{Locked="MSBuild"}{Locked="Visual Studio 2026"}LOCALIZATION: .NET, MSBuild, and Visual Studio 2026 should not be localized. diff --git a/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs b/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs index 19fe1325aff..17ce121dcff 100644 --- a/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs +++ b/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs @@ -107,38 +107,5 @@ public override bool Execute() } #endif } - - /// - /// Test that MSBuild.exe can successfully build a project with a task without Runtime="NET". - /// This verifies we didn't break normal CLI execution. - /// - [WindowsOnlyFact] - public void MSBuildCLI_WithoutDotNetRuntime_Succeeds() - { - using (var env = TestEnvironment.Create(_output)) - { - // Create a simple project that uses a built-in task - string projectContent = @" - - - - -"; - - var projectFile = env.CreateFile("test.proj", projectContent).Path; - - // Execute MSBuild on the project - should succeed - string output = RunnerUtilities.ExecMSBuild($"\"{projectFile}\" /t:TestTarget", out bool success, _output); - - // Build should succeed - success.ShouldBeTrue(); - - // Output should not contain MSB4233 error - output.ShouldNotContain("MSB4233"); - - // Should see our message - output.ShouldContain("Hello from MSBuild"); - } - } } } From 4685ebc486e3bba9341c92e7392d01b01c96cf4a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Oct 2025 22:28:50 +0000 Subject: [PATCH 10/15] Simplify CLI test to use ProcessIdTask from repo build - Remove custom task building code from MSBuildCLI_WithDotNetRuntimeTask_ShowsClearError - Use ProcessIdTask from Microsoft.Build.Engine.UnitTests assembly (same as EndToEnd test) - Remove unused System.IO using statement - Test is now simpler, faster, and consistent with the EndToEnd test Co-authored-by: rainersigwald <3347530+rainersigwald@users.noreply.github.com> --- .../DotNetRuntimeTask_CLI_Tests.cs | 62 +++---------------- 1 file changed, 9 insertions(+), 53 deletions(-) diff --git a/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs b/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs index 17ce121dcff..61426caf8f4 100644 --- a/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs +++ b/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.IO; using Microsoft.Build.UnitTests.Shared; using Shouldly; using Xunit; @@ -35,64 +34,21 @@ public void MSBuildCLI_WithDotNetRuntimeTask_ShowsClearError() #if NETFRAMEWORK using (var env = TestEnvironment.Create(_output)) { - // Create a simple .NET task DLL content for testing - string taskAssemblyContent = @" -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; - -namespace TestTasks -{ - public class SimpleTask : Task - { - public override bool Execute() - { - Log.LogMessage(MessageImportance.High, ""SimpleTask executed""); - return true; - } - } -}"; - - // Create the task assembly project - string taskProjectContent = @" - - - net472 - - - - - -"; - - var taskProjectFile = env.CreateFile("SimpleTask.csproj", taskProjectContent).Path; - var taskSourceFile = env.CreateFile("SimpleTask.cs", taskAssemblyContent).Path; - - // Build the task assembly (this should succeed) - string buildTaskOutput = RunnerUtilities.ExecMSBuild($"\"{taskProjectFile}\" /t:Build /v:m", out bool taskBuildSuccess); - - // If task build fails, skip the test as it's an environment issue, not what we're testing - if (!taskBuildSuccess) - { - _output.WriteLine("Warning: Could not build test task assembly. Skipping test."); - _output.WriteLine(buildTaskOutput); - return; - } - - string taskAssemblyPath = Path.Combine(Path.GetDirectoryName(taskProjectFile), "bin", "Debug", "net472", "SimpleTask.dll"); - - // Now create a project that uses the task with Runtime="NET" - string projectContent = $@" + // Use the same ProcessIdTask from Microsoft.Build.Engine.UnitTests that is built during the repo build + string projectContent = @" - - - + + + + + "; var projectFile = env.CreateFile("test.proj", projectContent).Path; // Execute MSBuild on the project - should fail with MSB4233 - string output = RunnerUtilities.ExecMSBuild($"\"{projectFile}\" /t:TestTarget", out bool success, _output); + string output = RunnerUtilities.ExecMSBuild($"\"{projectFile}\" /t:TestTask", out bool success, _output); // Build should fail success.ShouldBeFalse(); @@ -101,7 +57,7 @@ public override bool Execute() output.ShouldContain("MSB4233"); // Output should contain clear error message about .NET runtime not being supported - output.ShouldContain("SimpleTask"); + output.ShouldContain("ProcessIdTask"); output.ShouldContain(".NET runtime"); output.ShouldContain("MSBuild 18.0"); } From af1610e67fded1accb6865823d8879c69b9bc739 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Oct 2025 22:58:33 +0000 Subject: [PATCH 11/15] Use AssemblyFile instead of AssemblyName in CLI test - Change UsingTask to use AssemblyFile with the actual path to ProcessIdTask assembly - Get path using typeof(ProcessIdTask).Assembly.Location - This ensures MSBuild CLI can locate the task without relying on assembly resolution - Add System using statement for typeof Co-authored-by: rainersigwald <3347530+rainersigwald@users.noreply.github.com> --- src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs b/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs index 61426caf8f4..c6fea7ea9cd 100644 --- a/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs +++ b/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using Microsoft.Build.UnitTests.Shared; using Shouldly; using Xunit; @@ -35,9 +36,12 @@ public void MSBuildCLI_WithDotNetRuntimeTask_ShowsClearError() using (var env = TestEnvironment.Create(_output)) { // Use the same ProcessIdTask from Microsoft.Build.Engine.UnitTests that is built during the repo build - string projectContent = @" + // Get the path to the Microsoft.Build.Engine.UnitTests assembly + string taskAssemblyPath = typeof(Microsoft.Build.UnitTests.ProcessIdTask).Assembly.Location; + + string projectContent = $@" - + From e9715d0e12c26332107cd6a9fb7d31b22c090923 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Oct 2025 09:43:28 +0000 Subject: [PATCH 12/15] Fix CLI test compilation error - construct assembly path dynamically - Remove direct typeof(ProcessIdTask) reference that caused CS0234 error - Construct path to Microsoft.Build.Engine.UnitTests.dll dynamically at runtime - Use Assembly.GetExecutingAssembly().Location and Path.Combine - Add necessary using statements (System.IO, System.Reflection) - This avoids compile-time dependency on ProcessIdTask type Co-authored-by: YuliiaKovalova <95473390+YuliiaKovalova@users.noreply.github.com> --- src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs b/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs index c6fea7ea9cd..1076da5b670 100644 --- a/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs +++ b/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs @@ -1,7 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; +using System.IO; +using System.Reflection; using Microsoft.Build.UnitTests.Shared; using Shouldly; using Xunit; @@ -36,8 +37,11 @@ public void MSBuildCLI_WithDotNetRuntimeTask_ShowsClearError() using (var env = TestEnvironment.Create(_output)) { // Use the same ProcessIdTask from Microsoft.Build.Engine.UnitTests that is built during the repo build - // Get the path to the Microsoft.Build.Engine.UnitTests assembly - string taskAssemblyPath = typeof(Microsoft.Build.UnitTests.ProcessIdTask).Assembly.Location; + // Construct the path to the Microsoft.Build.Engine.UnitTests assembly dynamically + // since we don't have a direct reference to it from this test project + string currentAssemblyPath = Assembly.GetExecutingAssembly().Location; + string currentDirectory = Path.GetDirectoryName(currentAssemblyPath)!; + string taskAssemblyPath = Path.Combine(currentDirectory, "Microsoft.Build.Engine.UnitTests.dll"); string projectContent = $@" From cd458acb2774dce10cc1d64647acdc3014ba95b9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 6 Nov 2025 15:31:40 +0000 Subject: [PATCH 13/15] Fix nullable reference warning in test - extract error message to local variable Extract logger.Errors[0].Message to a local variable before calling ShouldContain to resolve CS8604 nullable reference warning. The variable assignment ensures the null-state analysis understands the value is not null. Co-authored-by: YuliiaKovalova <95473390+YuliiaKovalova@users.noreply.github.com> --- .../BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs b/src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs index f6d24d9fe0d..b711f19c52f 100644 --- a/src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs +++ b/src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs @@ -65,9 +65,10 @@ public void BuildManager_WithDotNetRuntimeTask_ShowsClearError() logger.Errors[0].Code.ShouldBe("MSB4233"); // Error message should contain the task name and indicate .NET runtime is not supported - logger.Errors[0].Message.ShouldContain("ProcessIdTask"); - logger.Errors[0].Message.ShouldContain(".NET runtime"); - logger.Errors[0].Message.ShouldContain("MSBuild 18.0"); + string errorMessage = logger.Errors[0].Message; + errorMessage.ShouldContain("ProcessIdTask"); + errorMessage.ShouldContain(".NET runtime"); + errorMessage.ShouldContain("MSBuild 18.0"); } #endif } From 0d76afa019c793c29a8b74dcdeaeaf13dfdc198b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 6 Nov 2025 16:37:52 +0000 Subject: [PATCH 14/15] Fix all nullable reference warnings in test files - Add null-forgiving operator and ShouldNotBeNull assertion for error message - This resolves CS8600 and CS8604 nullable reference warnings - Tests now properly handle nullable string from logger.Errors[0].Message Co-authored-by: YuliiaKovalova <95473390+YuliiaKovalova@users.noreply.github.com> --- .../BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs b/src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs index b711f19c52f..8a4185d2412 100644 --- a/src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs +++ b/src/Build.UnitTests/BackEnd/DotNetRuntimeTask_EndToEnd_Tests.cs @@ -65,7 +65,8 @@ public void BuildManager_WithDotNetRuntimeTask_ShowsClearError() logger.Errors[0].Code.ShouldBe("MSB4233"); // Error message should contain the task name and indicate .NET runtime is not supported - string errorMessage = logger.Errors[0].Message; + string? errorMessage = logger.Errors[0].Message; + errorMessage.ShouldNotBeNull(); errorMessage.ShouldContain("ProcessIdTask"); errorMessage.ShouldContain(".NET runtime"); errorMessage.ShouldContain("MSBuild 18.0"); From dd7467d1b7046a7917a6ab122f992971bea14ff4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 6 Nov 2025 20:26:41 +0000 Subject: [PATCH 15/15] Fix CLI test to locate Microsoft.Build.Engine.UnitTests.dll correctly The test was failing because it tried to load the assembly from the wrong directory. Now it properly navigates to the sibling Microsoft.Build.Engine.UnitTests output directory to find the DLL. Co-authored-by: YuliiaKovalova <95473390+YuliiaKovalova@users.noreply.github.com> --- src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs b/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs index 1076da5b670..cc31ed1c8d6 100644 --- a/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs +++ b/src/MSBuild.UnitTests/DotNetRuntimeTask_CLI_Tests.cs @@ -38,10 +38,12 @@ public void MSBuildCLI_WithDotNetRuntimeTask_ShowsClearError() { // Use the same ProcessIdTask from Microsoft.Build.Engine.UnitTests that is built during the repo build // Construct the path to the Microsoft.Build.Engine.UnitTests assembly dynamically - // since we don't have a direct reference to it from this test project + // The assembly is in a sibling directory: ../Microsoft.Build.Engine.UnitTests/net472/Microsoft.Build.Engine.UnitTests.dll string currentAssemblyPath = Assembly.GetExecutingAssembly().Location; string currentDirectory = Path.GetDirectoryName(currentAssemblyPath)!; - string taskAssemblyPath = Path.Combine(currentDirectory, "Microsoft.Build.Engine.UnitTests.dll"); + // Navigate to parent directory and then to the Build.UnitTests assembly directory + string taskAssemblyPath = Path.Combine(currentDirectory, "..", "Microsoft.Build.Engine.UnitTests", Path.GetFileName(currentDirectory), "Microsoft.Build.Engine.UnitTests.dll"); + taskAssemblyPath = Path.GetFullPath(taskAssemblyPath); string projectContent = $@"