diff --git a/src/Tasks.UnitTests/CombineTargetFrameworkInfoProperties_Tests.cs b/src/Tasks.UnitTests/CombineTargetFrameworkInfoProperties_Tests.cs
new file mode 100644
index 00000000000..ea0a3b0f166
--- /dev/null
+++ b/src/Tasks.UnitTests/CombineTargetFrameworkInfoProperties_Tests.cs
@@ -0,0 +1,37 @@
+// 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.Framework;
+using Microsoft.Build.Tasks;
+using Shouldly;
+using Xunit;
+
+namespace Microsoft.Build.UnitTests
+{
+ public sealed class CombineTargetFrameworkInfoProperties_Tests
+ {
+ ///
+ /// https://github.com/dotnet/msbuild/issues/8320
+ ///
+ [Theory]
+ [InlineData(null, false, "MSB3991")]
+ [InlineData("", false, "MSB3991")]
+ [InlineData(null, true, "MSB3992")]
+ public void RootElementNameNotValid(string rootElementName, bool UseAttributeForTargetFrameworkInfoPropertyNames, string errorCode)
+ {
+ MockEngine e = new MockEngine();
+ var task = new CombineTargetFrameworkInfoProperties();
+ task.BuildEngine = e;
+ var items = new ITaskItem[]
+ {
+ new TaskItemData("ItemSpec1", null)
+ };
+ task.RootElementName = rootElementName;
+ task.PropertiesAndValues = items;
+ task.UseAttributeForTargetFrameworkInfoPropertyNames = UseAttributeForTargetFrameworkInfoPropertyNames;
+ task.Execute().ShouldBe(false);
+ e.AssertLogContains(errorCode);
+ }
+ }
+}
diff --git a/src/Tasks/CombineTargetFrameworkInfoProperties.cs b/src/Tasks/CombineTargetFrameworkInfoProperties.cs
index 6830ba9cb99..7506fbc8be0 100644
--- a/src/Tasks/CombineTargetFrameworkInfoProperties.cs
+++ b/src/Tasks/CombineTargetFrameworkInfoProperties.cs
@@ -18,7 +18,6 @@ public class CombineTargetFrameworkInfoProperties : TaskExtension
/// The root element name to use for the generated XML string
///
public string RootElementName { get; set; }
-
///
/// Items to include in the XML. The ItemSpec should be the property name, and it should have Value metadata for its value.
///
@@ -39,16 +38,24 @@ public override bool Execute()
{
if (PropertiesAndValues != null)
{
- XElement root = UseAttributeForTargetFrameworkInfoPropertyNames ?
- new("TargetFramework", new XAttribute("Name", EscapingUtilities.Escape(RootElementName))) :
- new(RootElementName);
-
- foreach (ITaskItem item in PropertiesAndValues)
+ if ((!UseAttributeForTargetFrameworkInfoPropertyNames && string.IsNullOrEmpty(RootElementName)) || (UseAttributeForTargetFrameworkInfoPropertyNames && RootElementName == null))
{
- root.Add(new XElement(item.ItemSpec, item.GetMetadata("Value")));
+ string resource = UseAttributeForTargetFrameworkInfoPropertyNames ? "CombineTargetFrameworkInfoProperties.NotNullRootElementName" : "CombineTargetFrameworkInfoProperties.NotNullAndEmptyRootElementName";
+ Log.LogErrorWithCodeFromResources(resource, nameof(RootElementName), nameof(UseAttributeForTargetFrameworkInfoPropertyNames));
}
+ else
+ {
+ XElement root = UseAttributeForTargetFrameworkInfoPropertyNames ?
+ new("TargetFramework", new XAttribute("Name", EscapingUtilities.Escape(RootElementName))) :
+ new(RootElementName);
- Result = root.ToString();
+ foreach (ITaskItem item in PropertiesAndValues)
+ {
+ root.Add(new XElement(item.ItemSpec, item.GetMetadata("Value")));
+ }
+
+ Result = root.ToString();
+ }
}
return !Log.HasLoggedErrors;
}
diff --git a/src/Tasks/Resources/Strings.resx b/src/Tasks/Resources/Strings.resx
index fdf44f5268a..8b337bb2db5 100644
--- a/src/Tasks/Resources/Strings.resx
+++ b/src/Tasks/Resources/Strings.resx
@@ -2985,6 +2985,18 @@
PFX signing not supported on .NET Core.
+
+
+
+ MSB3991: '{0}' is not set or empty. When {1} is false, make sure to set a non-empty value for '{0}'.
+ {StrBegin="MSB3991: "}
+
+
+ MSB3992: '{0}' is not set. When {1} is true, make sure to set a value for '{0}'.
+ {StrBegin="MSB3992: "}
+