在Windows中使用PowerShell 5.1及更早版本并尝试使用Get-ChildItem
命令(其中文件夹路径长于260个字符)列出文件夹的内容时,会导致“ItemNotFoundException
”或错误“The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.
”。
当我试图通过前置“\\?\
”来绕过这个限制时,它根本不返回任何东西,如果我尝试用[System.IO.DirectoryInfo]
查找目录,我会得到和以前一样的“太长”错误。
在Windows Server 2016和Windows 10中,我似乎可以通过在注册表项“HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem
”下将DWORD“LongPathsEnabled
”设置为1
来解决这个问题,但这对于我们环境中运行旧版本Windows或PowerShell的系统不起作用。
我希望PowerShell/.NET在我前面加上“\\?\
”时接受长路径,但它仍然坚持路径太长,尽管下面链接的Microsoft文章建议这样做:https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation
2条答案
按热度按时间hs1ihplo1#
我发布这个问题纯粹是因为我想出了一个很好的答案,即 * 不 * 需要通过P/Invoke加载本机Win32 DLL,* 不 * 需要设置任何注册表项,不需要回退到调用任何本机可执行文件,* 并且 * 似乎可以一直工作到Windows Server 2012 R2(我没有任何旧版本可以测试)。
简短回答:
在当前的PowerShell会话中运行以下内容,或者在脚本中预先添加它(这在未来版本的PowerShell/NET中可能不起作用,因为它使用内部和未记录的API):
字符串
说明:
在ILSpy中查看了几个小时的反编译视图“
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscorlib.dll
”之后,我确定像System.IO.DirectoryInfo
这样的.NET API调用了内部静态方法System.IO.Path.NormalizePath
,该方法对您提供的文件路径执行初始验证。然后检查内部布尔值
System.AppContextSwitches.UseLegacyPathHandling
,如果设置为true
,它将拒绝接受长度超过260个字符的路径,* 即使 * 您使用文档中的“\\?\
”前缀!最难的是禁用“UseLegacyPathHandling”。通常情况下,你会在应用程序的“
app.config
”中添加一行<AppContextSwitchOverrides value="Switch.System.IO.UseLegacyPathHandling=false" />
(老实说,这可能也适用于PowerShell),但是如果你想在运行时做到这一点,而不修改你所使用的系统,这将是一个痛苦的过程。理想情况下,简单地运行
[System.AppContext]::SetSwitch('Switch.System.IO.UseLegacyPathHandling', $false)
* 应该 * 工作,除了.NET试图聪明地缓存这些开关的值,这样如果它们已经被访问过,它们基本上会停留在第一次访问时设置的任何值。这就是它变得丑陋的地方:在上面的代码片段中,我将缓存的值重置回
0
,内部System.AppContextSwitches.GetCachedSwitchValue方法(技术上实际上是GetCachedSwitchValueInternal
)使用该值来表示开关的值尚未缓存,应该通过公共方法AppContext.TryGetSwitch
进行查找。根据我的经验,只有这样,它才真正尊重您通过
System.AppContext.SetSwitch
(PowerShell中的语法是[System.AppContext]::SetSwitch
)设置的值。好好享受吧!
dluptydi2#
这些绕过方法仅适用于Powershell 5.1及以上版本,因此使用它们的唯一方法是将已安装的Windows Management Framework(WMF)版本更新到至少5.1。有关要求的详细信息以及不同版本Windows的安装程序链接,请参见https://learn.microsoft.com/en-us/powershell/scripting/windows-powershell/wmf/setup/install-configure?view=powershell-7.3
我最近在一个旧的Windows 2012盒子上遇到了同样的问题。