diff --git a/src/System.Management.Automation/engine/LanguagePrimitives.cs b/src/System.Management.Automation/engine/LanguagePrimitives.cs
index 3176fbbead1..b697e8e750f 100644
--- a/src/System.Management.Automation/engine/LanguagePrimitives.cs
+++ b/src/System.Management.Automation/engine/LanguagePrimitives.cs
@@ -310,9 +310,11 @@ public static class LanguagePrimitives
internal static void CreateMemberNotFoundError(PSObject pso, DictionaryEntry property, Type resultType)
{
- string availableProperties = GetAvailableProperties(pso);
+ string settableProperties = GetSettableProperties(pso);
- string message = StringUtil.Format(ExtendedTypeSystem.PropertyNotFound, property.Key.ToString(), resultType.FullName, availableProperties);
+ string message = settableProperties == string.Empty
+ ? StringUtil.Format(ExtendedTypeSystem.NoSettableProperty, property.Key.ToString(), resultType.FullName)
+ : StringUtil.Format(ExtendedTypeSystem.PropertyNotFound, property.Key.ToString(), resultType.FullName, settableProperties);
typeConversion.WriteLine("Issuing an error message about not being able to create an object from hashtable.");
throw new InvalidOperationException(message);
@@ -4735,18 +4737,23 @@ internal static PSObject SetObjectProperties(object o, IDictionary properties, T
return pso;
}
- private static string GetAvailableProperties(PSObject pso)
+ private static string GetSettableProperties(PSObject pso)
{
+ if (pso is null || pso.Properties is null)
+ {
+ return string.Empty;
+ }
+
StringBuilder availableProperties = new StringBuilder();
bool first = true;
- if (pso != null && pso.Properties != null)
+ foreach (PSPropertyInfo p in pso.Properties)
{
- foreach (PSPropertyInfo p in pso.Properties)
+ if (p.IsSettable)
{
if (!first)
{
- availableProperties.Append(" , ");
+ availableProperties.Append(", ");
}
availableProperties.Append("[" + p.Name + " <" + p.TypeNameOfValue + ">]");
diff --git a/src/System.Management.Automation/resources/ExtendedTypeSystem.resx b/src/System.Management.Automation/resources/ExtendedTypeSystem.resx
index 86b3f826324..3a84b103102 100644
--- a/src/System.Management.Automation/resources/ExtendedTypeSystem.resx
+++ b/src/System.Management.Automation/resources/ExtendedTypeSystem.resx
@@ -352,7 +352,10 @@
"{0}" returned a null value.
- The {0} property was not found for the {1} object. The available property is: {2}
+ The property '{0}' was not found for the '{1}' object. The settable properties are: {2}.
+
+
+ The property '{0}' was not found for the '{1}' object. There is no settable property available.
Cannot create object of type "{0}". {1}
diff --git a/test/powershell/Language/Scripting/HashtableToPSCustomObjectConversion.Tests.ps1 b/test/powershell/Language/Scripting/HashtableToPSCustomObjectConversion.Tests.ps1
index 09570e0e1e9..8d0d1ac24fe 100644
--- a/test/powershell/Language/Scripting/HashtableToPSCustomObjectConversion.Tests.ps1
+++ b/test/powershell/Language/Scripting/HashtableToPSCustomObjectConversion.Tests.ps1
@@ -142,3 +142,44 @@ Describe "Tests for hashtable to PSCustomObject conversion" -Tags "CI" {
}
}
+Describe "Error message with settable Property information" {
+ BeforeAll {
+ Add-Type @"
+namespace HashtableConversionTest {
+ public class AType {
+ public string Name;
+ public string Path { get; set; }
+ public string Id { get; }
+ }
+}
+"@
+ }
+
+ It "Only settable properties are called out in the error message" {
+ try {
+ [HashtableConversionTest.AType]@{ key = 1 }
+ } catch {
+ $e = $_
+ }
+
+ $e.FullyQualifiedErrorId | Should -BeExactly "ObjectCreationError"
+ $e.Exception.Message.Contains("key") | Should -BeTrue
+ $e.Exception.Message.Contains("Name") | Should -BeTrue
+ $e.Exception.Message.Contains("Path") | Should -BeTrue
+ $e.Exception.Message.Contains("Id") | Should -BeFalse
+ }
+
+ It "Shows no property when there is no settable property" {
+ try {
+ [System.Collections.Specialized.OrderedDictionary]@{ key = 1 }
+ } catch {
+ $e = $_
+ }
+
+ $type = [psobject].Assembly.GetType("ExtendedTypeSystem")
+ $property = $type.GetProperty("NoSettableProperty", @("NonPublic", "Static"))
+ $resString = $property.GetValue($null) -f 'key', 'System.Collections.Specialized.OrderedDictionary'
+
+ $e.Exception.Message | Should -BeLike "*$resString"
+ }
+}