powershellaclaccess-denied

Get-ChildItem -force reports "Access Denied" on My Documents folder and other junction points


I have a script that I wrote that replaces files. I pass params to it for the name of the file, and the base location to search from. The worker lines are:

$SubLocations = Get-ChildItem -Path $Startlocation -Recurse -include $Filename -Force  | 
                Where { $_.FullName.ToUpper().contains($Filter.ToUpper())}

I set $Startlocation to "C:\Users", however, I am getting access denied when trying to recurse through other users folders. I'm full admin on the machine, and I have already tried running powershell as admin. I can access all the files via Windows explorer with no issue. Any idea?

Get-ChildItem : Access to the path 'C:\Users\jepa227\Documents\My Music' is denied.
At C:\Users\krla226\Google Drive\Documents\PowerShell\Replace-File.ps1:35 char:46
+ $SubLocations = Get-ChildItem <<<<  -Path $Startlocation -Recurse -    include $Filename -Force | 
    + CategoryInfo          : PermissionDenied: (C:\Users\jepa227\Documents\My     Music:String) [Get-ChildItem], Una 
   uthorizedAccessException
+ FullyQualifiedErrorId :  DirUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand

UPDATE

While I was unable to get it working via GCI, I was able to use WMI to solve my problem. For those interested:

$SubLocations = Get-WmiObject -Class cim_datafile -Filter "fileName = '$filename' AND Extension = '$extension'" | 
                            Where { $_.Name.ToUpper().contains($Filter.ToUpper()) }

Solution

  • I was able to reproduce this on a Windows 7 machine with the following command logged in as an admin user named "admin", running powershell with elevated privileges, and UAC disabled:

    get-childitem "c:\users\Admin\my documents"
    

    and

    cd "c:\users\admin\my documents"
    get-childitem
    

    Based on the article here, it looks like My Documents, My Music, etc., are defined as junction points for backwards-compatibility with pre-Vista software. Powershell doesn't natively do well with junction points. It seems like there are a couple options here:

    1) Remove the -force from the Get-ChildItem command. This is likely your best bet.

    get-childitem c:\users -recurse
    

    works without error and skips junction points and system directories like AppData.

    Editor's note: Omitting -Force does solve the immediate problem, but invariably skips all hidden items, not just the hidden junction points that cause the access-denied errors.

    2) If you absolutely need to use the -Force for some reason, you could programmatically recurse each subdirectory, skipping junction points. This article describes the mechanism to identify junction points. A skeleton of this in a .ps1 script file might look like:

    Param( [Parameter(Mandatory=$true)][string]$startLocation )
    
    $errorActionPreference = "Stop"
    
    function ProcessDirectory( $dir )
    {
      Write-Host ("Working on " + $dir.FullName)
    
      # Work on the files in this folder here
      $filesToProcess = ( gci | where { ($_.PsIsContainer -eq 0) } ) # and file matches the requested pattern
      # process files
    
      $subdirs = gci $dir.FullName -force | where {($_.Attributes -band [IO.FileAttributes]::ReparsePoint) -eq 0 -and ($_.PsIsContainer -eq 1) -and (![string]::IsNullOrEmpty($_.FullName))}
    
      foreach( $subdir in $subdirs )
      {
          # Write-Host( $subdir.Name + ", " + $subdir.FullName )
         if ( $subdir -ne $null )
         {
           ProcessDirectory -dir $subdir
         }
      }
    }
    
    $dirs = get-childitem $startLocation -force
    $dirs | foreach { ProcessDirectory -dir $_ }