Отслеживание путей к недоступным папкам из Get-Childitem

#powershell #error-handling #get-childitem

#powershell #обработка ошибок #get-childitem

Вопрос:

Я работаю над небольшим скриптом для захвата хэшей файлов в работающей системе. У меня есть только Powershell.

Это активная часть кода:

 get-childitem -path $path -filter $filename -Recurse -Force | Select FullName | foreach-object { get-filehash $_.fullname | select * }
 

это команда, с помощью которой я тестирую:

 ./Get-FileHashesRecursive.ps1 -path c: -filename *.txt
 

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

ошибка выглядит следующим образом в окне консоли:

 get-childitem : Access to the path 'C:$Recycle.BinS-1-5-21-4167544967-4010527683-3770225279-9182' is denied.
At E:gitGet-RemoteFileHashesRecursiveGet-FileHashesRecursive.ps1:14 char:9
          get-childitem -path $path -filter $filename -Recurse -Force | ...
          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      CategoryInfo          : PermissionDenied: (C:$Recycle.Bin...3770225279-9182:String) [Get-ChildItem], UnauthorizedAccessException
      FullyQualifiedErrorId : DirUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand
 

Есть ли способ, которым я могу захватить путь или всю первую строку ошибки, НЕ останавливая выполнение остальной части скрипта?

Комментарии:

1. Почему бы не добавить -ErrorVariable FailedItems -ErrorAction SilentlyContinue к вашим Get-ChildItem параметрам, а затем, как только вы завершите свою команду, добавьте еще один, что-то вроде этого, $FailedItems | Foreach-Object {$_.CategoryInfo.TargetName} | Out-File "C:UserssailingbikerukDesktopnoaccess.log" . Надеюсь, затем вы должны получить файл со списком всех каталогов, которые выдавали ошибки UnauthorizedAccessException

2. Возможно, будет полезно также включить этот -File параметр в вашу Get-ChildItem команду!

Ответ №1:

Как и было запрошено, вот мои предыдущие комментарии в качестве ответа:

 Get-ChildItem -Path $Path -Filter $Filename -File -Recurse -Force -ErrorVariable FailedItems -ErrorAction SilentlyContinue | ForEach-Object { Get-FileHash -Path $_.FullName | Select-Object * }
$FailedItems | Foreach-Object {$_.CategoryInfo.TargetName} | Out-File "C:UserssailingbikerukDesktopnoaccess.log"
 
  • Я добавил -File параметр в Get-ChildItem , потому что вы специально имеете дело только с файлами.
  • Я также добавил параметры -ErrorVariable и -ErrorAction в Get-ChildItem команду. -ErrorVariable FailedItems определяет пользовательское имя для переменной, которая хранит ошибки из команды во время обработки. -ErrorAction SilentlyContinue , сообщает сценарию продолжить, не уведомляя вас об ошибках.
  • Как только ваша команда завершит обработку, вы можете проанализировать содержимое $FailedItems переменной. В приведенном выше примере я вывел файл TargetName в файл, чтобы вы могли прочитать его на досуге (пожалуйста, не забудьте при необходимости изменить путь к файлу и его имя, если вы также захотите вывести его в файл).

Комментарии:

1. ErrorRecord имеет элемент TargetObject , который также хранит путь. Есть ли причина для предпочтения CategoryInfo.TargetName ?

2. Спасибо за это, я протестирую это в выходные и отмечу как ответ после тестирования. Я не знал о параметре -ErrorVariable , который может оказаться очень полезным в будущем.

3. @zett42 Как бы вы получили доступ к targetObject, можете ли вы расширить свой комментарий в качестве ответа?

4. @Compo извиняется за задержку в любом ответе. Я попробовал ваше решение, и оно работает, если ошибка «доступ запрещен», но, похоже, она не создает запись в ErrorVariable, если ошибка есть The file <filename> cannot be read: The process cannot access the file <filename> because it is being used by another process . У меня нет уверенности в том, что он сообщает обо всех ошибках доступа.

5. Это совершенно другой вопрос, и по прошествии десяти дней, без принятия ответа, который, как вы заявили, работает и который полностью отвечает на заданный вопрос, я не собираюсь публиковать для вас другое решение для этого нового вопроса в рамках этого. Когда я отвечаю на вопрос, я не подписываюсь на то, чтобы быть специалистом службы поддержки forever для ваших дальнейших вопросов. Пожалуйста, создайте новый вопрос, если он у вас есть, и, пожалуйста, если он у вас есть, помните, что мы помогаем вам с исправлением конкретной воспроизводимой проблемы для предоставленного вами кода, мы не пишем для вас код для добавления новых функций, которые вы не включили.