在现有文件上设置属性时出现错误“找不到路径的一部分”

时间:2019-10-10 13:48:20

标签: powershell

我写了一个powershell脚本,将R / H / S属性从一组指定的根路径中剥离掉。相关代码为:

$Mask = [System.IO.FileAttributes]::ReadOnly.Value__ -bor [System.IO.FileAttributes]::Hidden.Value__ -bor [System.IO.FileAttributes]::System.Value__
Get-ChildItem -Path $Paths -Force -Recurse -ErrorAction SilentlyContinue | ForEach-Object {
    $Value = $_.Attributes.value__
    if($Value -band $Mask) {
        $Value = $Value -band -bnot $Mask
        if($PSCmdlet.ShouldProcess($_.FullName, "Set $([System.IO.FileAttributes] $Value)")) {
            $_.Attributes = $Value
        }
    }
}

这可以正常工作,但是在处理一个非常大的文件夹结构时,出现了如下错误:

Exception setting "Attributes": "Could not find a part of the path 'XXXXXXXXXX'."
At YYYYYYYYYY\Grant-FullAccess.ps1:77 char:17
+                 $_.Attributes = $Value
+                 ~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], SetValueInvocationException
    + FullyQualifiedErrorId : ExceptionWhenSetting

我发现这很奇怪,因为被操纵的FileInfo对象来自文件搜索,因此保证存在。

我不能提供文件名,因为它们是机密的,但是我可以说:

  • 它们长113-116个字符
  • 涉及的唯一字符集为%()+-.0123456789ABCDEFGIKLNOPRSTUVWX,在文件名中没有一个非法字符
  • 由于URL编码的空格(%),%20字符在那里

您对导致此问题的原因有何建议?我假设如果完整路径太长,或者我没有对该文件的写入权限,那么将抛出一个更适当的错误。

2 个答案:

答案 0 :(得分:0)

尽管有错误消息的措辞,但毕竟确实是一个漫长的问题。简单的Get-ChildItem搜索文件会产生相同的错误。我最终找到了错误消息中提到的文件,并测量了它们的总路径长度。他们超过了260个字符。

我尝试在路径中添加\\?\前缀,但是powershell似乎不喜欢这种语法。

幸运的是,该脚本正在Windows 2016上使用,因此我尝试在组策略中启用long path support。这样就解决了整个问题。

答案 1 :(得分:0)

your own answer中所述,问题竟然是一条漫长的路径(超过259个字符。)

除了通过组策略启用长途支持之外,您还可以通过注册表 在每台计算机上启用它,如下所示:请遵循以下步骤,这要求以海拔高度(以管理员身份)运行:

# NOTE: Must be run elevated (as admin).
# Change will take effect in FUTURE sessions.
Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem LongPathsEnabled 1

传递0以关闭支持。


但是,即使支持长路径的功能已关闭(在Windows 10之前的版本中总是如此),也可以处理长路径,即如果使用< em>长路径前缀,\\?\

注意事项:前缀\\?\仅在以下情况下有效:

  • 前缀路径必须为 完整(绝对),规范化路径(不得包含...组件)

    • 例如\\?\C:\path\to\foo.txt有效,但\\?\.\foo.txt无效。
    • 此外,如果路径是 UNC 路径,则该路径需要使用其他形式:
      • \\?\UNC\<server>\<share>\...;
      • 例如\\server1\share2必须表示为\\?\UNC\server1\share2
  • ... -在PowerShell Core 中,当前必须使用cmdlet的-LiteralPath参数,例如{{1} }和Get-ChildItem (尽管与Get-Item一起使用,Remove-Item也可以与-Path一起使用,如果您通过按位置传递路径,则隐含此参数)。 / p>

  • 不幸的是,从PowerShell v7.0开始,其他一些cmdlet和功能不适用于\\?\前缀的路径,特别是> / {{1 }},在PowerShell Core中,>>Set-Location