diff --git a/src/MSBuild.UnitTests/XMake_Tests.cs b/src/MSBuild.UnitTests/XMake_Tests.cs
index 4173c747739..43976f7e022 100644
--- a/src/MSBuild.UnitTests/XMake_Tests.cs
+++ b/src/MSBuild.UnitTests/XMake_Tests.cs
@@ -888,6 +888,38 @@ public void GetStarOutputsToFileIfRequested(string extraSwitch, string result)
result.ShouldContain("MSB1068");
}
+ ///
+ /// Regression test for issue where getTargetResult/getItem would throw an unhandled exception
+ /// when the item spec contained illegal path characters (e.g. compiler command line flags).
+ ///
+ [Theory]
+ [InlineData("-getTargetResult:GetCompileCommands", "\"Result\": \"Success\"")]
+ [InlineData("-getItem:CompileCommands", "\"Identity\":")]
+ public void GetTargetResultWithIllegalPathCharacters(string extraSwitch, string expectedContent)
+ {
+ using TestEnvironment env = TestEnvironment.Create();
+ // Create a project that mimics the ClangTidy target - it outputs items with illegal path characters
+ // (compiler command line flags) as the item spec.
+ TransientTestFile project = env.CreateFile("testProject.csproj", @"
+
+
+
+
+
+
+
+
+
+
+
+");
+ string results = RunnerUtilities.ExecMSBuild($" {project.Path} /t:GetCompileCommands {extraSwitch}", out bool success);
+ // The build should succeed instead of throwing an unhandled exception
+ success.ShouldBeTrue(results);
+ // The output should contain the expected content
+ results.ShouldContain(expectedContent);
+ }
+
[Theory]
[InlineData(true)]
[InlineData(false)]
diff --git a/src/MSBuild/JsonOutputFormatter.cs b/src/MSBuild/JsonOutputFormatter.cs
index cdc166849ca..a3c2f0afc9d 100644
--- a/src/MSBuild/JsonOutputFormatter.cs
+++ b/src/MSBuild/JsonOutputFormatter.cs
@@ -67,7 +67,7 @@ internal void AddItemInstancesInJsonFormat(string[] itemNames, ProjectInstance p
continue;
}
- jsonItem[metadatumName] = item.GetMetadataValue(metadatumName);
+ jsonItem[metadatumName] = TryGetMetadataValue(item, metadatumName);
}
itemArray.Add(jsonItem);
@@ -108,7 +108,7 @@ internal void AddItemsInJsonFormat(string[] itemNames, Project project)
continue;
}
- jsonItem[metadatumName] = item.GetMetadataValue(metadatumName);
+ jsonItem[metadatumName] = TryGetMetadataValue(item, metadatumName);
}
itemArray.Add(jsonItem);
@@ -147,7 +147,7 @@ internal void AddTargetResultsInJsonFormat(string[] targetNames, BuildResult res
continue;
}
- jsonItem[metadatumName] = item.GetMetadata(metadatumName);
+ jsonItem[metadatumName] = TryGetMetadata(item, metadatumName);
}
outputArray.Add(jsonItem);
@@ -159,5 +159,62 @@ internal void AddTargetResultsInJsonFormat(string[] targetNames, BuildResult res
_topLevelNode["TargetResults"] = targetResultsNode;
}
+
+ ///
+ /// Attempts to get metadata from an ITaskItem. If the metadata is a built-in metadata
+ /// (like FullPath, Directory, etc.) and the item spec contains illegal path characters,
+ /// this will catch the InvalidOperationException and return an empty string.
+ ///
+ private static string TryGetMetadata(ITaskItem item, string metadataName)
+ {
+ try
+ {
+ return item.GetMetadata(metadataName);
+ }
+ catch (InvalidOperationException)
+ {
+ // Built-in metadata like FullPath, Directory, etc. require path computation.
+ // If the item spec contains illegal path characters, return empty string.
+ return string.Empty;
+ }
+ }
+
+ ///
+ /// Attempts to get metadata value from a ProjectItemInstance. If the metadata is a built-in metadata
+ /// (like FullPath, Directory, etc.) and the item spec contains illegal path characters,
+ /// this will catch the InvalidOperationException and return an empty string.
+ ///
+ private static string TryGetMetadataValue(ProjectItemInstance item, string metadataName)
+ {
+ try
+ {
+ return item.GetMetadataValue(metadataName);
+ }
+ catch (InvalidOperationException)
+ {
+ // Built-in metadata like FullPath, Directory, etc. require path computation.
+ // If the item spec contains illegal path characters, return empty string.
+ return string.Empty;
+ }
+ }
+
+ ///
+ /// Attempts to get metadata value from a ProjectItem. If the metadata is a built-in metadata
+ /// (like FullPath, Directory, etc.) and the item spec contains illegal path characters,
+ /// this will catch the InvalidOperationException and return an empty string.
+ ///
+ private static string TryGetMetadataValue(ProjectItem item, string metadataName)
+ {
+ try
+ {
+ return item.GetMetadataValue(metadataName);
+ }
+ catch (InvalidOperationException)
+ {
+ // Built-in metadata like FullPath, Directory, etc. require path computation.
+ // If the item spec contains illegal path characters, return empty string.
+ return string.Empty;
+ }
+ }
}
}