Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,9 @@ public async Task<bool> ExecuteInternal()
{
ITaskItem project = Projects[i];

AbsolutePath projectPath = TaskEnvironment.GetAbsolutePath(FileUtilities.AttemptToShortenPath(project.ItemSpec));

AbsolutePath projectPath = FrameworkFileUtilities.FixFilePath(
TaskEnvironment.GetAbsolutePath(project.ItemSpec).GetCanonicalForm());

if (StopOnFirstFailure && !success)
{
// Inform the user that we skipped the remaining projects because StopOnFirstFailure=true.
Expand Down
16 changes: 16 additions & 0 deletions src/Tasks.UnitTests/MSBuild_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public void ProjectItemSpecTooLong()
{
MSBuild msbuildTask = new MSBuild
{
TaskEnvironment = TaskEnvironmentHelper.CreateForTest(),
BuildEngine = new MockEngine(_testOutput),

Projects = new ITaskItem[] { new TaskItem(projectFile1) }
Expand Down Expand Up @@ -123,6 +124,7 @@ public void OutputItemsAreTaggedWithProjectFileAndTargetName()
try
{
MSBuild msbuildTask = new MSBuild();
msbuildTask.TaskEnvironment = TaskEnvironmentHelper.CreateForTest();
msbuildTask.BuildEngine = new MockEngine();

msbuildTask.Projects = new ITaskItem[] { new TaskItem(projectFile1), new TaskItem(projectFile2) };
Expand Down Expand Up @@ -519,6 +521,7 @@ public void DifferentGlobalPropertiesWithDefault()
projects[3].SetMetadata("Properties", "MyProp=1");

MSBuild msbuildTask = new MSBuild();
msbuildTask.TaskEnvironment = TaskEnvironmentHelper.CreateForTest();
msbuildTask.BuildEngine = new MockEngine();
msbuildTask.Projects = projects;
msbuildTask.Properties = new string[] { "MyProp=0" };
Expand Down Expand Up @@ -577,6 +580,7 @@ public void DifferentGlobalPropertiesWithoutDefault()
projects[3].SetMetadata("Properties", "MyProp=1");

MSBuild msbuildTask = new MSBuild();
msbuildTask.TaskEnvironment = TaskEnvironmentHelper.CreateForTest();
msbuildTask.BuildEngine = new MockEngine();

msbuildTask.Projects = projects;
Expand Down Expand Up @@ -633,6 +637,7 @@ public void DifferentGlobalPropertiesWithBlanks()
projects[3].SetMetadata("Properties", "MyProp=1");

MSBuild msbuildTask = new MSBuild();
msbuildTask.TaskEnvironment = TaskEnvironmentHelper.CreateForTest();
msbuildTask.BuildEngine = new MockEngine();

msbuildTask.Projects = projects;
Expand Down Expand Up @@ -688,6 +693,7 @@ public void DifferentGlobalPropertiesInvalid()
projects[3].SetMetadata("Properties", "=;1");

MSBuild msbuildTask = new MSBuild();
msbuildTask.TaskEnvironment = TaskEnvironmentHelper.CreateForTest();
msbuildTask.BuildEngine = new MockEngine();

msbuildTask.Projects = projects;
Expand Down Expand Up @@ -735,6 +741,7 @@ public void DifferentAdditionalPropertiesWithDefault()
projects[1].SetMetadata("AdditionalProperties", "MyPropA=0");

MSBuild msbuildTask = new MSBuild();
msbuildTask.TaskEnvironment = TaskEnvironmentHelper.CreateForTest();
msbuildTask.BuildEngine = new MockEngine();
msbuildTask.Properties = new string[] { "MyPropG=1" };
msbuildTask.Projects = projects;
Expand Down Expand Up @@ -794,6 +801,7 @@ public void DifferentAdditionalPropertiesWithGlobalProperties()
projects[1].SetMetadata("Properties", "MyPropG=0");

MSBuild msbuildTask = new MSBuild();
msbuildTask.TaskEnvironment = TaskEnvironmentHelper.CreateForTest();
msbuildTask.BuildEngine = new MockEngine();
msbuildTask.Projects = projects;

Expand Down Expand Up @@ -849,6 +857,7 @@ public void DifferentAdditionalPropertiesWithoutDefault()
projects[1].SetMetadata("AdditionalProperties", "MyPropA=1");

MSBuild msbuildTask = new MSBuild();
msbuildTask.TaskEnvironment = TaskEnvironmentHelper.CreateForTest();
msbuildTask.BuildEngine = new MockEngine();
msbuildTask.Projects = projects;

Expand Down Expand Up @@ -907,6 +916,7 @@ public void TargetsWithSeparationChars()
};

MSBuild msbuildTask = new MSBuild();
msbuildTask.TaskEnvironment = TaskEnvironmentHelper.CreateForTest();
msbuildTask.BuildEngine = new MockEngine();
msbuildTask.Projects = projects;

Expand Down Expand Up @@ -957,6 +967,7 @@ public void StopOnFirstFailureandBuildInParallelSingleNode()
for (int i = 0; i < 4; i++)
{
MSBuild msbuildTask = new MSBuild();
msbuildTask.TaskEnvironment = TaskEnvironmentHelper.CreateForTest();
// By default IsMultipleNodesIs false
MockEngine mockEngine = new MockEngine();
mockEngine.IsRunningMultipleNodes = false;
Expand Down Expand Up @@ -1059,6 +1070,7 @@ public void StopOnFirstFailureandBuildInParallelMultipleNode()
for (int i = 0; i < 4; i++)
{
MSBuild msbuildTask = new MSBuild();
msbuildTask.TaskEnvironment = TaskEnvironmentHelper.CreateForTest();
MockEngine mockEngine = new MockEngine();
mockEngine.IsRunningMultipleNodes = true;
msbuildTask.BuildEngine = mockEngine;
Expand Down Expand Up @@ -1157,6 +1169,7 @@ public void SkipRemainingProjects()
};

MSBuild msbuildTask = new MSBuild();
msbuildTask.TaskEnvironment = TaskEnvironmentHelper.CreateForTest();
MockEngine mockEngine = new MockEngine();
mockEngine.IsRunningMultipleNodes = true;
msbuildTask.BuildEngine = mockEngine;
Expand All @@ -1174,6 +1187,7 @@ public void SkipRemainingProjects()
};

msbuildTask = new MSBuild();
msbuildTask.TaskEnvironment = TaskEnvironmentHelper.CreateForTest();
mockEngine = new MockEngine();
mockEngine.IsRunningMultipleNodes = true;
msbuildTask.BuildEngine = mockEngine;
Expand Down Expand Up @@ -1221,6 +1235,7 @@ public void TargetStopOnFirstFailureBuildInParallel()
{
// Test the case where the error is in the last target
MSBuild msbuildTask = new MSBuild();
msbuildTask.TaskEnvironment = TaskEnvironmentHelper.CreateForTest();
MockEngine mockEngine = new MockEngine();
msbuildTask.BuildEngine = mockEngine;
msbuildTask.Projects = projects;
Expand Down Expand Up @@ -1338,6 +1353,7 @@ public void PropertiesWithSeparationChars()
};

MSBuild msbuildTask = new MSBuild();
msbuildTask.TaskEnvironment = TaskEnvironmentHelper.CreateForTest();
msbuildTask.BuildEngine = new MockEngine();
msbuildTask.Projects = projects;

Expand Down
1 change: 1 addition & 0 deletions src/Tasks/CallTarget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace Microsoft.Build.Tasks
/// id validation checks to fail.
/// </remarks>
[RunInMTA]
[MSBuildMultiThreadableTask]
public class CallTarget : TaskExtension
{
#region Properties
Expand Down
9 changes: 7 additions & 2 deletions src/Tasks/MSBuild.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ namespace Microsoft.Build.Tasks
/// RequestBuilder which spawned them.
/// </remarks>
[RunInMTA]
public class MSBuild : TaskExtension
[MSBuildMultiThreadableTask]
public class MSBuild : TaskExtension, IMultiThreadableTask
Copy link
Copy Markdown
Member

@danmoseley danmoseley Mar 3, 2026

Choose a reason for hiding this comment

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

Multi is not a word, per guidelines it should be capitalized as IMultithreadableTask I believe

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good point, we missed it on the API review. We, unfortunately, already shipped this version.

{
/// <summary>
/// Enum describing the behavior when a project doesn't exist on disk.
Expand Down Expand Up @@ -187,6 +188,9 @@ public string SkipNonexistentProjects
/// </summary>
public string[] TargetAndPropertyListSeparators { get; set; }

/// <inheritdoc />
public TaskEnvironment TaskEnvironment { get; set; }

#endregion

#region ITask Members
Expand Down Expand Up @@ -276,7 +280,8 @@ public override bool Execute()
{
ITaskItem project = Projects[i];

string projectPath = FileUtilities.AttemptToShortenPath(project.ItemSpec);
AbsolutePath projectPath = FrameworkFileUtilities.FixFilePath(
TaskEnvironment.GetAbsolutePath(project.ItemSpec).GetCanonicalForm());

if (StopOnFirstFailure && !success)
{
Expand Down