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:
parent
3125764476
commit
ce4c35b9ed
|
@ -1153,8 +1153,22 @@ namespace System.Management.Automation
|
||||||
|
|
||||||
internal class NativeMethods
|
internal class NativeMethods
|
||||||
{
|
{
|
||||||
[DllImport(PinvokeDllNames.GetFileAttributesDllName, CharSet = CharSet.Unicode, SetLastError = true)]
|
private static string EnsureLongPathPrefixIfNeeded(string path)
|
||||||
internal static extern int GetFileAttributes(string lpFileName);
|
{
|
||||||
|
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]
|
[Flags]
|
||||||
internal enum FileAttributes
|
internal enum FileAttributes
|
||||||
|
|
|
@ -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" {
|
Describe "Extended FileSystem Item/Content Cmdlet Provider Tests" -Tags "Feature" {
|
||||||
BeforeAll {
|
BeforeAll {
|
||||||
$testDir = "testDir"
|
$testDir = "testDir"
|
||||||
|
|
Loading…
Reference in a new issue