Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

powershell - Error "Could not find a part of the path" while setting attributes on an existing file

I wrote a powershell script to strip R/H/S attributes off all files in a specified set of root paths. The relevant code is:

$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
        }
    }
}

This works fine, but when processing one very large folder structure, I got a few errors like this:

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

I find this strange because the FileInfo object being manipulated is guaranteed to exist, since it comes from a file search.

I can't give the file names because they are confidential, but I can say:

  • they are 113-116 characters long
  • the unique set of characters involved are %()+-.0123456789ABCDEFGIKLNOPRSTUVWX, none of which are illegal in a file name
  • the % character is there due to URL-encoded spaces (%20)

Do you have any suggestions as to what may be causing this? I assume that if the full path was too long, or I didn't have write permissions to the file, then a more appropriate error would be thrown.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As stated in your own answer, the problem turned out to be an overly long path (longer than the legacy limit of 259 chars.)

In addition to enabling long-path support via Group Policy, you can enable it on a per-computer basis via the registry as follows, which requires running with elevation (as admin):

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

Pass 0 to turn support off.


However, even with long-path supported turned OFF (as is invariably the case on pre-Windows 10 versions) it is possible to handle long paths:

  • In Windows PowerShell (PowerShell up to version 5.1), you must use the long-path opt-in prefix, \?, as discussed below.

  • In PowerShell [Core] v6+, no extra work is needed, because it always supports long paths - you neither need to turn on support system-wide nor do you need the long-path prefix discussed below.

    • Caveat: While you may use \? in PowerShell [Core] as well in principle, support for it is inconsistent as of v7.0.0-rc.2; see this GitHub issue.

Important: Prefix \? only works under the following conditions:

  • The prefixed path must be a full (absolute), normalized path (must not contain . or .. components).

    • E.g., \?C:pathofoo.txt works, but \?.foo.txt does not.
    • Furthermore, if the path is a UNC path, the path requires a different form:
      • \?UNC<server><share>...;
      • E.g., \server1share2 must be represented as \?UNCserver1share2

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...