-
Notifications
You must be signed in to change notification settings - Fork 7.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Windows (NTFS): Inconsistent support for the long-path prefix (\\?\) in filesystem paths #10805
Comments
LocalGlobbing code is very sensitive and it seems it is not covered by tests explicitly - I think it is main stopper of a progress here. |
As of PowerShell Core 7.0.0-rc.2 I've noticed that the |
Long paths is Windows feature, not PS Core. It seems we have a test for long path support. |
Yes, it only applies on Windows, as hopefully clearly implied by the issue title. PS Core should support the long-path prefix there too, and support has degraded from Windows PowerShell, and even further since v7.0.0-preview.4 What I was trying to say: In PowerShell Core on Windows, you can seemingly access paths longer than 259 chars. even without the |
You can run the tests from the initial post; for me, 7 out of the 11 tests fail as of v7.0.0-rc.2 |
I don't understand how PowerShell Core can work with long paths if the feature is not enabled on Windows 10. |
That is a fair question, @iSazonov - I haven't looked into the why and how, but you can try it yourself: First, open an elevated session and run the following, to turn system-wide support for long paths off: Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem LongPathsEnabled 0 Then, open a regular session and run the following: Set-Location; 'hi' > ('x'*(259 - "$pwd".length)); (Get-Item x*).FullName.Length; Remove-Item x* You'll get no error message and Running the same code in Windows PowerShell fails. Perhaps |
@mklement0 Please share your Windows 10 version. I guess latest versions can have the feature enabled by default. |
It's |
@mklement0 If you replace 259 in your test with more large value (what about 400?) you get an error. |
That is an unrelated constraint: even in long paths the individual components must not be longer than 255 chars., as far as I know. You'd have to design the test differently to get longer paths. |
Ah :-) my bad. |
I don't see the behavior you're seeing; try the following code, which creates a directory path that is itself longer than 259 chars., then a file in it, targets the directory with both Push-Location ($dir = mkdir -force ($env:TEMP + "\$pid\" + 'x' * 250)); $file = "$pwd\test.txt"; 'hi' > $file; "dir path length: $($dir.FullName.Length)`nfile path length: $($file.length)"; Get-Item $dir; '###'; Get-ChildItem $dir; '###'; Get-Item $file; '###'; Set-Location $dir -passthru; Pop-Location; Remove-Item $file; Remove-Item (Split-Path $dir) -Recurse Output on my Windows 10 machine:
|
@mklement0 I found why I don't understand you :-)
|
😁 - thanks for digging deeper. |
.NET Core itself supports long file paths implicitly, while .NET Framework requires app opt-in. I get that users may want to use the |
Good to know that .NET Core supports long paths by default - seemingly even without the system-wide opt-in. The code that @iSazonov linked to seems to no longer be part of the repo (except for the tests, which don't use the
Given that the current behavior is clearly a regression from Windows PowerShell, I suggest either:
|
I am not sure we can fix this now. I think it must necessarily be in FileSystem provider V2. |
Understood, @iSazonov. With the intent to fix this eventually, the categorization shifts from breaking change to (known) bug, so please label this issue accordingly. |
Meta bug label :-) |
This should be listed as a Known Issue causing breaking changes until resolved. |
Is this related to why I can't create very long paths?
|
@musm, no, you're seeing a fundamental NTFS limitation that applies even when long-path support is enabled: individual file/directory names must not be longer than While you could argue that the error message technically applies, it is certainly vague. |
What is the state of this issue? I see that no one is assigned. Will this be a will-not-fix? |
Nice to have :-) |
How can this just be a nice to have? For file server administration it's very common for users to save things in ridiculously long paths, then when you come to doing maintenance and migrations you're not able to use powershell to work with them. I know there are workarounds for an individual file, but when you've got a server with millions of files on them and thousands of long paths, how are you supposed to automate anything? |
It is my headache :-( If supporting |
TL;DR : Just because .NET Core / .NET 5 / .NET 6 / .NET 7 those runtimes themselves support Be it .NET or Completely Native, each and every Long Path works on windows 10 v1607 and upwards with *per executables opt-in.* build the Special Note : This manifest file has to be embedded into each executables. File name must be <?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
<ws2:longPathAware>true</ws2:longPathAware>
</windowsSettings>
</application>
</assembly> Users who wish to use long path must Set Long Path Aware On system wide through Registry : Why System Wide Long Path is not on by default (?) according to a MS engineer : microsoft/WindowsAppSDK#875 (comment) Following APIs change behaviors after opt-in : CopyFileW, CopyFile2, CopyFileExW, CreateFileW, CreateFile2, CreateDirectoryW, CreateDirectoryExW GetCurrentDirectoryW, RemoveDirectoryW, SetCurrentDirectoryW, CreateHardLinkW, CreateSymbolicLinkW, DeleteFileW, FindFirstFileW, FindFirstFileExW, FindNextFileW, GetFileAttributesW, GetFileAttributesExW, SetFileAttributesW, GetFullPathNameW, GetLongPathNameW, MoveFileW, MoveFileExW, MoveFileWithProgressW, ReplaceFileW, SearchPathW, FindFirstFileNameW, FindNextFileNameW, FindFirstStreamW, FindNextStreamW, GetCompressedFileSizeW, GetFinalPathNameByHandleW. Ref:
|
@ghost The issue is about consistent support of |
I have a simple script that deletes all files in a particular folder. I have added the $TargetFolder = '\\?\C:\MyTemp\'
Get-ChildItem -LiteralPath $TargetFolder -Force | Remove-Item -Force -Recurse As a result of running this script in PowerShell 7.2.1, PowerShell attempted to delete all files in the C drive and the system was destroyed. Despite the fact that PowerShell 7 is advertised as being highly compatible with Windows PoweShell 5.1, this kind of behavior is ridiculous. |
@mkht Really PowerShell FileSystem Provider was never designed to support |
PR #15873 that has been merged into In the case of the |
I have worked around this issue by running test-path -literalPath "\?\C:\test" -ErrorAction:Stop and handling the exception. but now with a .Net framework update (4.8) this behaviour has changed again! I'm unable to find a reliable way to detect if it is supported (the error shows up with out-file -literalpath even if it stopped with test-path) |
For some god-forsaken reason, piping I can understand interpreting strings in the classic way to prevent breakage for any script that pipes a collection of wildcard strings to such functions (though I can't imagine why someone would), but it's extremely strange and unintuitive for |
So, is it going to be solved or not? PS7 does need to work with legacy "\?\UNC". |
Note: This is a generalization of #4439. @SteveL-MSFT, if you agree, please close the latter.
Prefixing full, normalized, native filesystem paths with
\\?\
allows targeting filesystem items whose path is longer than the legacy limit of 259 characters.Update:
\\?\
isn't needed in PS Core (in .NET Core altogether), so long paths just work as-is, even if not enabled system-wide.\\?\
is useful for targeting files or directories with irregular names, such as ones with trailing spaces, so you can remove them withRemove-Item
, for instance.As an aside: In Windows 10 you can now opt in system-wide to support long paths, but individual applications must also opt in (PowerShell indirectly does) - see https://blogs.msdn.microsoft.com/jeremykuhne/2016/07/30/net-4-6-2-and-long-paths-on-windows-10/
As of PowerShell Core 7.3.0-preview.2, the inconsistent support for
\\?\
is as follows:With the
-Path
parameter,\\?\
isn't supported at all , so wildcard expressions cannot be used.Get-Item
andGet-ChildItem
output nothing, andRemove-Item
is a quiet no-op (silent failure) too.With the
-LiteralPath
parameter in combination with\\?\
:Get-Item
andRemove-Item
complain about not finding the path.-Force
makesGet-Item
output a brokenDirectoryInfo
instance.Remove-Item
without-Recurse
on a nonempty directory presents the usual confirmation prompt (implying the ability to recognize the path as existent), but then fails on confirmation.Get-ChildItem
reports the root directory's content instead(!)Additionally,
\\?\
paths do not work in the following cases:With
>
/>>
, which implicitly behave likeOut-File -Path
- see Some scripts / files with wildcard metacharacter [ in the file name or path cannot be invoked or redirected to #4726In the same vein, invocation of an executable - whether with or without(no longer a problem as of PowerShell Core 7.3.0-preview.2)&
- is broken (possibly related to Some scripts / files with wildcard metacharacter [ in the file name or path cannot be invoked or redirected to #4726 as well).(no longer a problem as of PowerShell Core 7.3.0-preview.2)Start-Process
Set-Location
(not even with-LiteralPath
)Note:
Some of these problems are regressions from Windows PowerShell, where only the invocation /
Start-Process
tests fail and>
only with a new file.I haven't looked into whether invoking an executable with an overly long path is supported in principle by the underlying APIs.
Steps to reproduce
Run the following from a Pester test script (
*.Tests.ps1
) on Windows:Expected behavior
All tests should pass.
Actual behavior
All tests but the first one fail, with various error messages.
Environment data
The text was updated successfully, but these errors were encountered: