mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Fix share completion with provider and spaces (#19440)
This commit is contained in:
@@ -4478,14 +4478,15 @@ namespace System.Management.Automation
|
||||
var wordToComplete = context.WordToComplete;
|
||||
var quote = HandleDoubleAndSingleQuote(ref wordToComplete);
|
||||
|
||||
// First, try to match \\server\share
|
||||
// support both / and \ when entering UNC paths for typing convenience (#17111)
|
||||
var shareMatch = Regex.Match(wordToComplete, @"^(?:\\\\|//)([^\\/]+)(?:\\|/)([^\\/]*)$");
|
||||
// Matches file shares with and without the provider name and with either slash direction.
|
||||
// Avoids matching Windows device paths like \\.\CDROM0 and \\?\Volume{b8f3fc1c-5cd6-4553-91e2-d6814c4cd375}\
|
||||
var shareMatch = s_shareMatch.Match(wordToComplete);
|
||||
if (shareMatch.Success)
|
||||
{
|
||||
// Only match share names, no filenames.
|
||||
var server = shareMatch.Groups[1].Value;
|
||||
var sharePattern = WildcardPattern.Get(shareMatch.Groups[2].Value + "*", WildcardOptions.IgnoreCase);
|
||||
var provider = shareMatch.Groups[1].Value;
|
||||
var server = shareMatch.Groups[2].Value;
|
||||
var sharePattern = WildcardPattern.Get(shareMatch.Groups[3].Value + "*", WildcardOptions.IgnoreCase);
|
||||
var ignoreHidden = context.GetOption("IgnoreHiddenShares", @default: false);
|
||||
var shares = GetFileShares(server, ignoreHidden);
|
||||
if (shares.Count == 0)
|
||||
@@ -4498,13 +4499,20 @@ namespace System.Management.Automation
|
||||
{
|
||||
if (sharePattern.IsMatch(share))
|
||||
{
|
||||
string shareFullPath = "\\\\" + server + "\\" + share;
|
||||
if (quote != string.Empty)
|
||||
string sharePath = $"\\\\{server}\\{share}";
|
||||
string completionText;
|
||||
if (quote == string.Empty)
|
||||
{
|
||||
shareFullPath = quote + shareFullPath + quote;
|
||||
completionText = share.Contains(' ')
|
||||
? $"'{provider}{sharePath}'"
|
||||
: $"{provider}{sharePath}";
|
||||
}
|
||||
else
|
||||
{
|
||||
completionText = $"{quote}{provider}{sharePath}{quote}";
|
||||
}
|
||||
|
||||
shareResults.Add(new CompletionResult(shareFullPath, shareFullPath, CompletionResultType.ProviderContainer, shareFullPath));
|
||||
shareResults.Add(new CompletionResult(completionText, share, CompletionResultType.ProviderContainer, sharePath));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5155,6 +5163,10 @@ namespace System.Management.Automation
|
||||
return result;
|
||||
}
|
||||
|
||||
private static readonly Regex s_shareMatch = new(
|
||||
@"(^Microsoft\.PowerShell\.Core\\FileSystem::|^FileSystem::|^)(?:\\\\|//)(?![.|?])([^\\/]+)(?:\\|/)([^\\/]*)$",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
private struct SHARE_INFO_1
|
||||
{
|
||||
|
||||
@@ -1931,6 +1931,10 @@ class InheritedClassTest : System.Attribute
|
||||
$res.CompletionMatches[0].CompletionText | Should -BeExactly $afterTab
|
||||
}
|
||||
|
||||
It "Tab completion UNC path with filesystem provider" -Skip:(!$IsWindows) {
|
||||
$res = TabExpansion2 -inputScript 'Filesystem::\\localhost\admin'
|
||||
$res.CompletionMatches[0].CompletionText | Should -BeExactly 'Filesystem::\\localhost\ADMIN$'
|
||||
}
|
||||
|
||||
It "Tab completion for registry" -Skip:(!$IsWindows) {
|
||||
$beforeTab = 'registry::HKEY_l'
|
||||
@@ -3115,6 +3119,18 @@ function MyFunction ($param1, $param2)
|
||||
}
|
||||
}
|
||||
|
||||
Describe "TabCompletion elevated tests" -Tags CI, RequireAdminOnWindows {
|
||||
It "Tab completion UNC path with spaces" -Skip:(!$IsWindows) {
|
||||
$Share = New-SmbShare -Temporary -ReadAccess (whoami.exe) -Path C:\ -Name "Test Share"
|
||||
$res = TabExpansion2 -inputScript '\\localhost\test'
|
||||
$res.CompletionMatches[0].CompletionText | Should -BeExactly "& '\\localhost\Test Share'"
|
||||
if ($null -ne $Share)
|
||||
{
|
||||
Remove-SmbShare -InputObject $Share -Force -Confirm:$false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Describe "Tab completion tests with remote Runspace" -Tags Feature,RequireAdminOnWindows {
|
||||
BeforeAll {
|
||||
$skipTest = -not $IsWindows
|
||||
|
||||
Reference in New Issue
Block a user