diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index 893cade7a..612d7f04d 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -1953,7 +1953,10 @@ namespace Microsoft.PowerShell.Commands { if (instance?.BaseObject is FileSystemInfo fileInfo) { - if (InternalSymbolicLinkLinkCodeMethods.IsReparsePointLikeSymlink(fileInfo)) + // Checking the cached attributes first avoids an extra filesystem query for every non-link, + // which is particularly expensive when formatting items on an SMB share. + if (InternalSymbolicLinkLinkCodeMethods.IsReparsePoint(fileInfo) + && InternalSymbolicLinkLinkCodeMethods.IsReparsePointLikeSymlink(fileInfo)) { return $"{PSStyle.Instance.FileInfo.SymbolicLink}{fileInfo.Name}{PSStyle.Instance.Reset} -> {fileInfo.LinkTarget}"; } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 index 4ddceaa68..977906790 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 @@ -237,6 +237,18 @@ Describe 'Formatting for FileInfo objects' -Tags 'CI' { $dir.NameString | Should -BeExactly "$($PSStyle.FileInfo.Directory + $dir.Name + $PSStyle.Reset)" } + It 'NameString should not query link metadata for a cached non-reparse point' -Skip:(-not $IsWindows) { + $testFile = Join-Path -Path $TestDrive -ChildPath 'cached-metadata' + $file = New-Item -ItemType File -Path $testFile + $null = $file.Attributes + + # Removing the file makes an unnecessary second filesystem query observable. + [System.IO.File]::Delete($testFile) + + # Without the cached-attributes check, NameString queries the deleted path for link metadata and throws. + [Microsoft.PowerShell.Commands.FileSystemProvider]::NameString($file) | Should -BeExactly $file.Name + } + It 'Executable should have correct color' { if ($IsWindows) { $exePath = Join-Path -Path $TestDrive -ChildPath 'myExe.exe'