Skip to content
Merged
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 @@ -193,6 +193,10 @@ public partial interface IBuildEngine5 : Microsoft.Build.Framework.IBuildEngine,
{
void LogTelemetry(string eventName, System.Collections.Generic.IDictionary<string, string> properties);
}
public partial interface IBuildEngine6 : Microsoft.Build.Framework.IBuildEngine, Microsoft.Build.Framework.IBuildEngine2, Microsoft.Build.Framework.IBuildEngine3, Microsoft.Build.Framework.IBuildEngine4, Microsoft.Build.Framework.IBuildEngine5
{
System.Collections.Generic.IReadOnlyDictionary<string, string> GetGlobalProperties();
}
public partial interface ICancelableTask : Microsoft.Build.Framework.ITask
{
void Cancel();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,10 @@ public partial interface IBuildEngine5 : Microsoft.Build.Framework.IBuildEngine,
{
void LogTelemetry(string eventName, System.Collections.Generic.IDictionary<string, string> properties);
}
public partial interface IBuildEngine6 : Microsoft.Build.Framework.IBuildEngine, Microsoft.Build.Framework.IBuildEngine2, Microsoft.Build.Framework.IBuildEngine3, Microsoft.Build.Framework.IBuildEngine4, Microsoft.Build.Framework.IBuildEngine5
{
System.Collections.Generic.IReadOnlyDictionary<string, string> GetGlobalProperties();
}
public partial interface ICancelableTask : Microsoft.Build.Framework.ITask
{
void Cancel();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@ protected Task(System.Resources.ResourceManager taskResources, string helpKeywor
public Microsoft.Build.Framework.IBuildEngine3 BuildEngine3 { get { throw null; } }
public Microsoft.Build.Framework.IBuildEngine4 BuildEngine4 { get { throw null; } }
public Microsoft.Build.Framework.IBuildEngine5 BuildEngine5 { get { throw null; } }
public Microsoft.Build.Framework.IBuildEngine6 BuildEngine6 { get { throw null; } }
protected string HelpKeywordPrefix { get { throw null; } set { } }
public Microsoft.Build.Framework.ITaskHost HostObject { get { throw null; } set { } }
public Microsoft.Build.Utilities.TaskLoggingHelper Log { get { throw null; } }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ protected Task(System.Resources.ResourceManager taskResources, string helpKeywor
public Microsoft.Build.Framework.IBuildEngine3 BuildEngine3 { get { throw null; } }
public Microsoft.Build.Framework.IBuildEngine4 BuildEngine4 { get { throw null; } }
public Microsoft.Build.Framework.IBuildEngine5 BuildEngine5 { get { throw null; } }
public Microsoft.Build.Framework.IBuildEngine6 BuildEngine6 { get { throw null; } }
protected string HelpKeywordPrefix { get { throw null; } set { } }
public Microsoft.Build.Framework.ITaskHost HostObject { get { throw null; } set { } }
public Microsoft.Build.Utilities.TaskLoggingHelper Log { get { throw null; } }
Expand Down
39 changes: 32 additions & 7 deletions src/Build.UnitTests/BackEnd/TaskHostConfiguration_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public void ConstructorWithNullName()
_continueOnErrorDefault,
null,
@"c:\my tasks\mytask.dll",
null,
null);
}
);
Expand Down Expand Up @@ -79,6 +80,7 @@ public void ConstructorWithEmptyName()
_continueOnErrorDefault,
String.Empty,
@"c:\my tasks\mytask.dll",
null,
null);
}
);
Expand Down Expand Up @@ -106,6 +108,7 @@ public void ConstructorWithNullLocation()
_continueOnErrorDefault,
"TaskName",
null,
null,
null);
}
);
Expand Down Expand Up @@ -135,6 +138,7 @@ public void ConstructorWithEmptyLocation()
_continueOnErrorDefault,
"TaskName",
String.Empty,
null,
null);
}
);
Expand Down Expand Up @@ -162,7 +166,9 @@ public void TestValidConstructors()
_continueOnErrorDefault,
"TaskName",
@"c:\MyTasks\MyTask.dll",
null,
null);

TaskHostConfiguration config2 = new TaskHostConfiguration(
1,
Directory.GetCurrentDirectory(),
Expand All @@ -178,6 +184,7 @@ public void TestValidConstructors()
_continueOnErrorDefault,
"TaskName",
@"c:\MyTasks\MyTask.dll",
null,
null);

IDictionary<string, object> parameters = new Dictionary<string, object>();
Expand All @@ -196,7 +203,8 @@ public void TestValidConstructors()
_continueOnErrorDefault,
"TaskName",
@"c:\MyTasks\MyTask.dll",
parameters);
parameters,
null);

IDictionary<string, object> parameters2 = new Dictionary<string, object>();
parameters2.Add("Text", "Hello!");
Expand All @@ -219,7 +227,8 @@ public void TestValidConstructors()
_continueOnErrorDefault,
"TaskName",
@"c:\MyTasks\MyTask.dll",
parameters2);
parameters2,
null);
}

/// <summary>
Expand All @@ -228,6 +237,12 @@ public void TestValidConstructors()
[Fact]
public void TestTranslationWithNullDictionary()
{
var expectedGlobalProperties = new Dictionary<string, string>
{
["Property1"] = "Value1",
["Property2"] = "Value2"
};

TaskHostConfiguration config = new TaskHostConfiguration(
1,
Directory.GetCurrentDirectory(),
Expand All @@ -243,7 +258,8 @@ public void TestTranslationWithNullDictionary()
_continueOnErrorDefault,
"TaskName",
@"c:\MyTasks\MyTask.dll",
null);
null,
expectedGlobalProperties);

((ITranslatable)config).Translate(TranslationHelpers.GetWriteTranslator());
INodePacket packet = TaskHostConfiguration.FactoryForDeserialization(TranslationHelpers.GetReadTranslator());
Expand All @@ -255,6 +271,8 @@ public void TestTranslationWithNullDictionary()
Assert.Equal(config.TaskLocation, deserializedConfig.TaskLocation);
#endif
Assert.Null(deserializedConfig.TaskParameters);

Assert.Equal(expectedGlobalProperties, deserializedConfig.GlobalProperties);
}

/// <summary>
Expand All @@ -278,7 +296,8 @@ public void TestTranslationWithEmptyDictionary()
_continueOnErrorDefault,
"TaskName",
@"c:\MyTasks\MyTask.dll",
new Dictionary<string, object>());
new Dictionary<string, object>(),
new Dictionary<string, string>());

((ITranslatable)config).Translate(TranslationHelpers.GetWriteTranslator());
INodePacket packet = TaskHostConfiguration.FactoryForDeserialization(TranslationHelpers.GetReadTranslator());
Expand All @@ -291,6 +310,9 @@ public void TestTranslationWithEmptyDictionary()
#endif
Assert.NotNull(deserializedConfig.TaskParameters);
Assert.Equal(config.TaskParameters.Count, deserializedConfig.TaskParameters.Count);

Assert.NotNull(deserializedConfig.GlobalProperties);
Assert.Equal(config.GlobalProperties.Count, deserializedConfig.GlobalProperties.Count);
}

/// <summary>
Expand All @@ -317,7 +339,8 @@ public void TestTranslationWithValueTypesInDictionary()
_continueOnErrorDefault,
"TaskName",
@"c:\MyTasks\MyTask.dll",
parameters);
parameters,
null);

((ITranslatable)config).Translate(TranslationHelpers.GetWriteTranslator());
INodePacket packet = TaskHostConfiguration.FactoryForDeserialization(TranslationHelpers.GetReadTranslator());
Expand Down Expand Up @@ -357,7 +380,8 @@ public void TestTranslationWithITaskItemInDictionary()
_continueOnErrorDefault,
"TaskName",
@"c:\MyTasks\MyTask.dll",
parameters);
parameters,
null);

((ITranslatable)config).Translate(TranslationHelpers.GetWriteTranslator());
INodePacket packet = TaskHostConfiguration.FactoryForDeserialization(TranslationHelpers.GetReadTranslator());
Expand Down Expand Up @@ -396,7 +420,8 @@ public void TestTranslationWithITaskItemArrayInDictionary()
_continueOnErrorDefault,
"TaskName",
@"c:\MyTasks\MyTask.dll",
parameters);
parameters,
null);

((ITranslatable)config).Translate(TranslationHelpers.GetWriteTranslator());
INodePacket packet = TaskHostConfiguration.FactoryForDeserialization(TranslationHelpers.GetReadTranslator());
Expand Down
72 changes: 72 additions & 0 deletions src/Build.UnitTests/BackEnd/TaskHost_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,78 @@ public void LogErrorAfterTaskIsDone()
}
#endif

/// <summary>
/// Verifies that tasks can get global properties.
/// </summary>
[Fact]
public void TasksCanGetGlobalProperties()
{
string projectFileContents = @"
<Project>
<UsingTask TaskName='test' TaskFactory='RoslynCodeTaskFactory' AssemblyFile='$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll'>
<Task>
<Code><![CDATA[
var globalProperties = ((IBuildEngine6)BuildEngine).GetGlobalProperties();

Log.LogMessage(""Global properties:"");
foreach (var item in globalProperties)
{
Log.LogMessage($""{item.Key}: '{item.Value}'"");
}
]]></Code>
</Task>
</UsingTask>
<Target Name='Build'>
<test/>
</Target>
</Project>";

Dictionary<string, string> globalProperties = new Dictionary<string, string>
{
["Property1"] = "Value_%",
["Property2"] = "Value_$",
["Property3"] = "Value_@",
["Property4"] = "Value_'",
["Property5"] = "Value_;",
["Property6"] = "Value_?",
["Property7"] = "Value_*",
};

MockLogger mockLogger = Helpers.BuildProjectWithNewOMExpectSuccess(projectFileContents, globalProperties);

foreach (var item in globalProperties)
{
mockLogger.AssertLogContains($"{item.Key}: '{item.Value}'");
}
}

/// <summary>
/// Verifies that if the user specifies no global properties, tasks get back an empty collection.
/// </summary>
[Fact]
public void TasksGetNoGlobalPropertiesIfNoneSpecified()
{
string projectFileContents = @"
<Project>
<UsingTask TaskName='test' TaskFactory='RoslynCodeTaskFactory' AssemblyFile='$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll'>
<Task>
<Code><![CDATA[
var globalProperties = ((IBuildEngine6)BuildEngine).GetGlobalProperties();

Log.LogMessage($""Global property count: {globalProperties.Count}"");
]]></Code>
</Task>
</UsingTask>
<Target Name='Build'>
<test/>
</Target>
</Project>";

MockLogger mockLogger = Helpers.BuildProjectWithNewOMExpectSuccess(projectFileContents);

mockLogger.AssertLogContains("Global property count: 0");
}

#region Helper Classes

/// <summary>
Expand Down
15 changes: 14 additions & 1 deletion src/Build/BackEnd/Components/RequestBuilder/TaskHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ internal class TaskHost :
#if FEATURE_APPDOMAIN
MarshalByRefObject,
#endif
IBuildEngine5
IBuildEngine6
{
/// <summary>
/// True if the "secret" environment variable MSBUILDNOINPROCNODE is set.
Expand Down Expand Up @@ -647,6 +647,19 @@ public void LogTelemetry(string eventName, IDictionary<string, string> propertie

#endregion

#region IBuildEngine6 Members

/// <summary>
/// Gets the global properties for the current project.
/// </summary>
/// <returns>An <see cref="IReadOnlyDictionary{String, String}" /> containing the global properties of the current project.</returns>
public IReadOnlyDictionary<string, string> GetGlobalProperties()
{
return _requestEntry.RequestConfiguration.GlobalProperties.ToDictionary();
}

#endregion

/// <summary>
/// Called by the internal MSBuild task.
/// Does not take the lock because it is called by another request builder thread.
Expand Down
3 changes: 2 additions & 1 deletion src/Build/Instance/TaskFactories/TaskHostTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,8 @@ public bool Execute()
BuildEngine.ContinueOnError,
_taskType.Type.FullName,
AssemblyUtilities.GetAssemblyLocation(_taskType.Type.GetTypeInfo().Assembly),
_setParameters
_setParameters,
new Dictionary<string, string>(_buildComponentHost.BuildParameters.GlobalProperties)
);

try
Expand Down
19 changes: 19 additions & 0 deletions src/Framework/IBuildEngine6.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Collections.Generic;

namespace Microsoft.Build.Framework
{
/// <summary>
/// This interface extends <see cref="IBuildEngine5" /> to allow tasks to get the current project's global properties.
/// </summary>
public interface IBuildEngine6 : IBuildEngine5
{
/// <summary>
/// Gets the global properties for the current project.
/// </summary>
/// <returns>An <see cref="IReadOnlyDictionary{String, String}" /> containing the global properties of the current project.</returns>
IReadOnlyDictionary<string, string> GetGlobalProperties();
}
}
15 changes: 14 additions & 1 deletion src/MSBuild/OutOfProcTaskHostNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ internal class OutOfProcTaskHostNode :
#if CLR2COMPATIBILITY
IBuildEngine3
#else
IBuildEngine5
IBuildEngine6
#endif
{
/// <summary>
Expand Down Expand Up @@ -442,6 +442,19 @@ public void LogTelemetry(string eventName, IDictionary<string, string> propertie

#endregion

#region IBuildEngine6 Implementation

/// <summary>
/// Gets the global properties for the current project.
/// </summary>
/// <returns>An <see cref="IReadOnlyDictionary{String, String}" /> containing the global properties of the current project.</returns>
public IReadOnlyDictionary<string, string> GetGlobalProperties()
{
return new Dictionary<string, string>(_currentConfiguration.GlobalProperties);
}

#endregion

#endif

#region INodePacketFactory Members
Expand Down
Loading