Allow use of long paths (#3960)

When calling Windows native API to determine if an item exists,
ensure the path is prepended with "\\?\" when the path is a long path.

Fixes #3891
This commit is contained in:
jeffbi 2017-06-07 17:13:51 -07:00 committed by Jason Shirk
parent 3125764476
commit ce4c35b9ed
2 changed files with 57 additions and 2 deletions

View file

@ -1153,8 +1153,22 @@ namespace System.Management.Automation
internal class NativeMethods
{
[DllImport(PinvokeDllNames.GetFileAttributesDllName, CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern int GetFileAttributes(string lpFileName);
private static string EnsureLongPathPrefixIfNeeded(string path)
{
if (path.Length >= MAX_PATH && !path.StartsWith(@"\\?\", StringComparison.Ordinal))
return @"\\?\" + path;
return path;
}
[DllImport(PinvokeDllNames.GetFileAttributesDllName, EntryPoint = "GetFileAttributesW", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int GetFileAttributesPrivate(string lpFileName);
internal static int GetFileAttributes(string fileName)
{
fileName = EnsureLongPathPrefixIfNeeded(fileName);
return GetFileAttributesPrivate(fileName);
}
[Flags]
internal enum FileAttributes

View file

@ -663,6 +663,47 @@ Describe "Copy-Item can avoid copying an item onto itself" -Tags "CI", "RequireA
}
}
Describe "Handling long paths" -Tags "CI" {
BeforeAll {
$longDir = 'a' * 250
$longSubDir = 'b' * 250
$fileName = "file1.txt"
$topPath = Join-Path $TestDrive $longDir
$longDirPath = Join-Path $topPath $longSubDir
$longFilePath = Join-Path $longDirPath $fileName
$cwd = Get-Location
}
BeforeEach {
New-Item -ItemType File -Path $longFilePath -Force | Out-Null
}
AfterEach {
Remove-Item -Path $topPath -Force -Recurse -ErrorAction SilentlyContinue
Set-Location $cwd
}
It "Can remove a file via a long path" {
Remove-Item -Path $longFilePath -ErrorVariable e -ErrorAction SilentlyContinue
$e | Should BeNullOrEmpty
$longFilePath | Should Not Exist
}
It "Can rename a file via a long path" {
$newFileName = "new-file.txt"
$newPath = Join-Path $longDirPath $newFileName
Rename-Item -Path $longFilePath -NewName $newFileName
$longFilePath | Should Not Exist
$newPath | Should Exist
}
It "Can change into a directory via a long path" {
Set-Location -Path $longDirPath -ErrorVariable e -ErrorAction SilentlyContinue
$e | Should BeNullOrEmpty
$c = Get-Location
$fileName | Should Exist
}
It "Can use Test-Path to check for a file via a long path" {
Test-Path $longFilePath | Should Be $true
}
}
Describe "Extended FileSystem Item/Content Cmdlet Provider Tests" -Tags "Feature" {
BeforeAll {
$testDir = "testDir"