From 461d6abc26fbb299107e87532f1b4557e2cba093 Mon Sep 17 00:00:00 2001 From: MartinGC94 Date: Wed, 29 Nov 2023 21:41:37 +0100 Subject: [PATCH 1/5] Fix completion crash for certain providers --- .../CommandCompletion/CompletionCompleters.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs b/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs index e2220750606..a5b5cca36ae 100644 --- a/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs +++ b/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs @@ -4767,17 +4767,20 @@ private static List GetDefaultProviderResults( // Save relevant info and try again to get just the names. foreach (dynamic child in childItemOutput) { - childrenInfoTable.Add(GetChildNameFromPsObject(child, provider.ItemSeparator), child.PSIsContainer); + // TryAdd is used because some providers (like SCCM) may include duplicate PSPaths in a container. + _ = childrenInfoTable.TryAdd(GetChildNameFromPsObject(child, provider.ItemSeparator), child.PSIsContainer); } _ = context.Helper.CurrentPowerShell .AddCommandWithPreferenceSetting("Microsoft.PowerShell.Management\\Get-ChildItem") .AddParameter("LiteralPath", pathInfo.Path) - .AddParameter("Name"); + .AddParameter("Name") + .AddCommandWithPreferenceSetting("Microsoft.PowerShell.Utility\\Sort-Object") + .AddParameter("Unique"); childItemOutput = context.Helper.ExecuteCurrentPowerShell(out _); - foreach (var child in childItemOutput) + foreach (PSObject child in childItemOutput) { - var childName = (string)child.BaseObject; + string childName = (string)child.BaseObject; childNameList.Add(childName); } } @@ -4786,8 +4789,11 @@ private static List GetDefaultProviderResults( foreach (dynamic child in childItemOutput) { var childName = GetChildNameFromPsObject(child, provider.ItemSeparator); - childrenInfoTable.Add(childName, child.PSIsContainer); - childNameList.Add(childName); + // TryAdd is used because some providers (like SCCM) may include duplicate PSPaths in a container. + if (childrenInfoTable.TryAdd(childName, child.PSIsContainer)) + { + childNameList.Add(childName); + } } } From beb71b8e1ce51411aaf117311929682d357e02eb Mon Sep 17 00:00:00 2001 From: MartinGC94 <42123497+MartinGC94@users.noreply.github.com> Date: Fri, 8 Dec 2023 01:16:27 +0100 Subject: [PATCH 2/5] Update src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs Co-authored-by: Ilya --- .../engine/CommandCompletion/CompletionCompleters.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs b/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs index 1b6817a44db..1f5c68fa31a 100644 --- a/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs +++ b/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs @@ -4786,6 +4786,7 @@ private static List GetDefaultProviderResults( foreach (dynamic child in childItemOutput) { var childName = GetChildNameFromPsObject(child, provider.ItemSeparator); + // TryAdd is used because some providers (like SCCM) may include duplicate PSPaths in a container. if (childrenInfoTable.TryAdd(childName, child.PSIsContainer)) { From 01dae9766e0059adb013f17a3eb4367ea4566961 Mon Sep 17 00:00:00 2001 From: MartinGC94 Date: Wed, 13 Dec 2023 16:42:58 +0100 Subject: [PATCH 3/5] Fix SCCM provider completion crash --- .../CommandCompletion/CompletionCompleters.cs | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs b/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs index 1f5c68fa31a..685996b2d57 100644 --- a/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs +++ b/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs @@ -4864,10 +4864,22 @@ private static List GetDefaultProviderResults( private static string GetChildNameFromPsObject(dynamic psObject, char separator) { - // The obvious solution would be to use the "PSChildName" property - // but some providers don't have it (like the Variable provider) - // So we use a substring of "PSPath" instead. - string childName = psObject.PSPath ?? string.Empty; + if (((PSObject)psObject).BaseObject is string result) + { + // The "Get-ChildItem" call for this provider returned a string that we assume is the child name. + // This is what the SCCM provider returns. + return result; + } + + string childName = psObject.PSChildName; + if (childName is not null) + { + return childName; + } + + // Some providers (Like the variable provider) don't include a PSChildName property + // so we get the child name from the path instead. + childName = psObject.PSPath ?? string.Empty; int ProviderSeparatorIndex = childName.IndexOf("::", StringComparison.Ordinal); childName = childName.Substring(ProviderSeparatorIndex + 2); int indexOfName = childName.LastIndexOf(separator); From ab72ca78f2f5b0c7310e9510dde74b1f958b5bed Mon Sep 17 00:00:00 2001 From: MartinGC94 Date: Wed, 13 Dec 2023 16:49:06 +0100 Subject: [PATCH 4/5] Revert unnecessary TryAdd changes. --- .../CommandCompletion/CompletionCompleters.cs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs b/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs index 685996b2d57..9028f0df640 100644 --- a/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs +++ b/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs @@ -4764,16 +4764,13 @@ private static List GetDefaultProviderResults( // Save relevant info and try again to get just the names. foreach (dynamic child in childItemOutput) { - // TryAdd is used because some providers (like SCCM) may include duplicate PSPaths in a container. - _ = childrenInfoTable.TryAdd(GetChildNameFromPsObject(child, provider.ItemSeparator), child.PSIsContainer); + childrenInfoTable.Add(GetChildNameFromPsObject(child, provider.ItemSeparator), child.PSIsContainer); } _ = context.Helper.CurrentPowerShell .AddCommandWithPreferenceSetting("Microsoft.PowerShell.Management\\Get-ChildItem") .AddParameter("LiteralPath", pathInfo.Path) - .AddParameter("Name") - .AddCommandWithPreferenceSetting("Microsoft.PowerShell.Utility\\Sort-Object") - .AddParameter("Unique"); + .AddParameter("Name"); childItemOutput = context.Helper.ExecuteCurrentPowerShell(out _); foreach (PSObject child in childItemOutput) { @@ -4786,12 +4783,8 @@ private static List GetDefaultProviderResults( foreach (dynamic child in childItemOutput) { var childName = GetChildNameFromPsObject(child, provider.ItemSeparator); - - // TryAdd is used because some providers (like SCCM) may include duplicate PSPaths in a container. - if (childrenInfoTable.TryAdd(childName, child.PSIsContainer)) - { - childNameList.Add(childName); - } + childrenInfoTable.Add(childName, child.PSIsContainer); + childNameList.Add(childName); } } From 032209e354eb647de22aeef8d68e0c5c4ce534b2 Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Tue, 16 Jan 2024 16:10:38 -0800 Subject: [PATCH 5/5] Remove whitespace characters in a new line --- .../engine/CommandCompletion/CompletionCompleters.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs b/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs index 0095d574168..bc1f1528900 100644 --- a/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs +++ b/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs @@ -4883,7 +4883,7 @@ private static string GetChildNameFromPsObject(dynamic psObject, char separator) return childName.Substring(indexOfName + 1); } - + /// /// Takes a path and rebuilds it with the specified variable replacements. /// Also escapes special characters as needed.