Как избежать UnathorizedAccessException при использовании Get-ChildItem?

Я использую PowerShell 5.0 и работаю над сценарием, чтобы рекурсивно найти и перечислить все версии log4net.dll в текущем каталоге.

Get-ChildItem log4net.dll -Recurse | % versioninfo | Export-Csv "C:\MyJunk\log4net.csv"

Приведенный выше оператор начинает возвращать информацию о версии, как и ожидалось, но выполнение останавливается на первой папке, на доступ к которой у меня нет прав:

Get-ChildItem : The specified network name is no longer available.
At line:1 char:1
+ Get-ChildItem log4net.dll -Recurse | % versioninfo | Export-Csv "C:\M ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : ReadError: (J:\ArcPlan_OracleWallet\Production:String) [Get-ChildItem], IOException
+ FullyQualifiedErrorId : DirIOError,Microsoft.PowerShell.Commands.GetChildItemCommand

Get-ChildItem : Access is denied
At line:1 char:1
+ Get-ChildItem log4net.dll -Recurse | % versioninfo | Export-Csv "C:\M ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [Get-ChildItem], UnauthorizedAccessException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.GetChildItemCommand

Я запускаю Windows PowerShell ISE в качестве администратора. ExecutionPolicy — RemoteSigned, а $ErrorActionPreference — Continue.

В идеале я хотел бы, чтобы сценарий опрашивал ACL каждой папки и обходил все папки (и их содержимое), на доступ к которым у меня нет прав. Однако другим решением будет обход жестко запрограммированных папок. Будучи новичком в PowerShell, я сосредоточился на последнем.

Я попытался обойти первую проблемную папку (по имени), чтобы посмотреть, смогу ли я заставить ее работать, но столкнулся с тем же исключением, и обработка останавливается.

Get-ChildItem log4net.dll -Recurse | Where-Object { $_.FullName -notmatch '\\ArcPlan_OracleWallet\\?'} | export-csv 'C:\MyJunk\log4net.csv'

Спасибо.


person Steve Brueckman    schedule 11.05.2017    source источник
comment
@Ансгар. Спасибо за повтор. Я все еще получаю исключение «Отказано в доступе».   -  person Steve Brueckman    schedule 11.05.2017
comment
The specified network name is no longer available это сообщение об ошибке неверно или действительно проблема с сетью? Может быть, поэтому выполнение скрипта останавливается?   -  person sodawillow    schedule 11.05.2017
comment
@sodawillow Я в это не верю. С помощью командной строки я могу открыть папку J:\ArcPlan_OracleWallet и просмотреть ее содержимое. Когда я пытаюсь cd production, я получаю отказ в доступе. ошибка.   -  person Steve Brueckman    schedule 12.05.2017
comment
Вы пробовали Get-ChildItem -Force?   -  person sodawillow    schedule 12.05.2017
comment
Я считаю, что проблема заключалась в том, что Get-ChildItem log4net.dll -Recurse потерпит неудачу до того, как Where-Object сможет отфильтровать нежелательные каталоги. Мое решение глупое. Это слишком долго, чтобы публиковать здесь, поэтому я добавлю его в качестве ответа ниже.   -  person Steve Brueckman    schedule 13.05.2017


Ответы (2)


Если вы хотите игнорировать ошибки, используйте -ErrorAction SilentlyContinue.

У этого параметра есть и другие полезные значения, как вы можете обнаружить здесь и здесь.

Вот хороший вопрос вполне по теме.

Вы также можете получить помощь по этому вопросу с помощью Get-Help about_CommonParameters.

(Привет и добро пожаловать, если вы копаете этот ответ, прочитайте это ^^).

person sodawillow    schedule 11.05.2017
comment
Я использую -ErrorAction SilentlyContinue довольно часто и обнаружил, что более короткий псевдоним -ea 4 легче и быстрее набирать. -ea — это псевдоним для -ErrorAction и 4, поскольку SilentlyContinue — это четвертый элемент в ActionPreference перечисление. - person TheMadTechnician; 11.05.2017
comment
Я думаю, что правильная короткая версия должна быть -ea 0 PS H:\> 0..5 | % {write-Host $_ ([System.Management.Automation.ActionPreference]$_)} 0 SilentlyContinue 1 Stop 2 Continue 3 Inquire 4 Ignore 5 Suspend - person Igor; 11.05.2017
comment
Я использовал if (Test-Connection $host -Quiet -Count 2 -EA 0) { #host is online, go on } много раз, прежде чем понял бит -EA 0 :) - person sodawillow; 11.05.2017
comment
@содавиллоу. Спасибо за информацию. SilentlyContinue скрывает ошибки, но команда все равно останавливается. - person Steve Brueckman; 11.05.2017
comment
@SteveBrueckman, посмотри мой комментарий к твоему вопросу, тогда давайте отладим еще немного :). - person sodawillow; 11.05.2017

Я считаю, что проблема заключалась в том, что Get-ChildItem log4net.dll -Recurse потерпит неудачу до того, как Where-Object сможет отфильтровать нежелательные каталоги.

Я хочу избежать жесткого кодирования каталогов, но пока что вот мое (неуклюжее) решение.

## Version information will be retrieved for $fileName
$fileName = 'log4net.dll'

$ErrorActionPreference = 'Continue'

## Get directies - excluding those you lack permission to access
$directories = Get-ChildItem -Directory | 
    Where-Object {$_.FullName -inotmatch 'directory-1' -and 
                $_.FullName -inotmatch 'directory-2' -and
                $_.FullName -inotmatch 'directory-3'                    
} 

## Array to hold version information
$allFilesVersionInfo = @()

foreach ($directory in $directories) {

    ## Get all files recursively
    $files = Get-ChildItem -Path $directory.FullName $fileName -Recurse 

    foreach ($file in $files) {

        ## Get version information and add to array
        $fileVersionInfo = $file | % versioninfo 
        $allFilesVersionInfo += $fileVersionInfo
    }
}

# Write version information in arra to file
$exportFullPath = "C:\MyJunk\$($fileName)-version.csv"
$allFilesVersionInfo |  Export-Csv -Path $($exportFullPath)
person Steve Brueckman    schedule 12.05.2017