Get-ChildItem-force сообщает "Доступ запрещен" в папке "Мои Документы" и других точках соединения

у меня есть скрипт, который я написал, который заменяет файлы. Я передаю ему параметры для имени файла и базового местоположения для поиска. Линий работника являются:

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

Я установил $Startlocation в "C:Users" тем не менее, я получаю отказ в доступе при попытке рекурсии через другие папки пользователей. Я полный администратор на машине, и я уже пробовал запустить powershell в качестве администратора. Я могу получить доступ ко всем файлам через Проводник Windows без проблем. Любой идея?

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

обновление

пока я не смог заставить его работать через GCI, я смог использовать WMI для решения моей проблемы. Для интересующихся:

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

2 ответов


я смог воспроизвести это на машине Windows 7 со следующей командой, вошедшей в систему как пользователь admin с именем "admin", запустив powershell с повышенными привилегиями и отключив UAC:

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

и

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

на основании статьи здесь, похоже, Мои Документы, моя музыка и т. д., определяются как точки соединения для обратной совместимости с программным обеспечением pre-Vista. Powershell изначально не очень хорошо справляется с точками соединения. Похоже есть несколько вариантов здесь:

1) Удалите-force из команды Get-ChildItem. Это, вероятно, ваш лучший выбор.

get-childitem c:\users -recurse

работает без ошибок и пропускает точки соединения и системные каталоги, такие как AppData.

Примечание редактора: опущение -Force решает непосредственную проблему, но неизменно пропускает все скрытые элементы, а не только скрытые точки соединения, которые вызывают ошибки отказа в доступе.

2) Если вам абсолютно необходимо использовать -Force по какой-то причине вы можете программно рекурсировать каждый подкаталог, пропуская точки соединения. в этой статье описывает механизм идентификации точек соединения. Скелет этого в a .файл сценария ps1 может выглядеть так:

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

полезный ответ mcating хорошо объясняет проблему.

быстро исправить он предлагает опустить -Force, который работает, потому что PowerShell игнорировать скрытые элементы, если , и эти определенные системой точки соединения имеют (рядом с ReparsePoint и System атрибуты).

Если вам нужен -Force для обработки скрытых элементов в целом и только хотите игнорировать их определенные системой точки соединения, вы можете использовать Get-ChildItem ' s следующим образом:

Get-ChildItem -Force -Recurse -Attributes !Hidden, !System, !ReparsePoint

на -Attributes стоимостью исключить все элементы все из набора следующих атрибутов:Hidden, System, ReparsePoint, что верно для всех заданных системой точек соединения.
Хотя технически возможно создать свои собственные точки соединения (или символические ссылки) с этими атрибутами, это вряд ли произойдет на практике.