Существует множество сообщений о том, как использовать Test-Path или [System.IO.File]::Exists(), чтобы проверить, существует ли файл или папка. Однако эти посты не дают каких-либо нюансов. Следующее вернет true:
Test-Path -Path "\\Server\Share\path that exists"
Это вернет false:
Test-Path -Path "\\Server\Share\path that doesn't exist"
Но это также вернет false:
Test-Path -Path "\\Server\Share\path that exists but can't be access because network issues"
Я подумал, что вместо этого могу использовать Get-Item и перехватить сообщение об ошибке, чтобы использовать тип ошибки, чтобы определить, был ли путь просто недоступен или он действительно не существует. Однако Get-Item просто возвращает ItemNotFoundException, даже если целевой путь должен существовать, но недоступен.
Есть ли способ отличить недоступный путь от пути, которого на самом деле не существует?
Обновлено: в Windows уже есть коды системных ошибок, которые могут сказать вам, не был ли файл найден, или это была проблема с сетью, или доступ запрещен и т. д. Я ищу способ использовать этот уровень детализации. чтобы выяснить, почему путь недоступен в Powershell.
Небольшая мысль: сначала проверьте «\\Server\Share», чтобы обнаружить проблемы с сетью (если вы точно знаете, что \\Server\Share существует). Затем проверьте подкаталог, чтобы обнаружить проблемы с не найденным путем. В качестве первого шага вы даже можете пропинговать «Сервер», чтобы определить, жив ли он, и только затем проверить наличие общего ресурса.
Так чего же вы ожидаете от него, если путь недоступен и кто-то просто изменил или удалил путь/файл откуда-то еще?
Почему бы ему не знать причину? Windows уже знает это по кодам ошибок. net helpmsg 5 = доступ запрещен, net helpmsg 2 = файл не найден, net helpmsg 53 = сетевой путь не найден и т. д. Поскольку Windows уже способна различать такие ситуации, я ожидаю, что в Powershell тоже будет какой-то способ сделать это. .





Короткий ответ: нет. По сути, вы спрашиваете, как узнать, существует ли путь на USB-накопителе... пока диск не подключен.
Более развернутый ответ: вроде? Лучшее, что вы можете сделать, это сначала проверить соединение с помощью Test-Connection или чего-то еще, что в случае неудачи должно дать вам объяснение неудавшегося соединения.
Этого МОЖЕТ быть достаточно в вашем случае, если вам просто нужно контролировать, недоступен ли путь из-за проблем с подключением.
Следующая функция PowerShell использует класс .NET DirectoryInfo для проверки существования пути и обработки исключений, которые предоставляют более подробную информацию об ошибке.
function Test-NetworkPath([string]$Path) {
try {
$dirInfo = [IO.DirectoryInfo]::new($Path)
if ($dirInfo.Exists) { Write-Host 'Path exists.' }
else {
Write-Host 'Path does not exist.'
# Attempt to access the directory to trigger an error for further diagnosis
$null = $dirInfo.GetDirectories()
}
}
catch [System.ArgumentNullException] {
Write-Host 'Path is null.'
}
catch [System.ArgumentException] {
Write-Host 'Path contains invalid characters such as ", <, >, or |.' # .NET Framework and .NET Core versions older than 2.1
}
catch [System.IO.PathTooLongException] {
Write-Host 'Path is too long.'
}
catch [System.IO.DirectoryNotFoundException] {
Write-Host 'Directory not found.'
}
catch [System.Security.SecurityException] {
Write-Host 'Path is inaccessible due to: Caller does not have the required permission.'
}
catch [System.IO.IOException] {
Write-Host 'Path is inaccessible, likely due to network issues.'
}
catch {
Write-Host ('Unexpected error: {0}' -f $_.Exception.GetType().FullName)
}
}
$dirInfo = [IO.DirectoryInfo]::new($Path)$Path сформирован неправильно.if ($dirInfo.Exists) { Write-Output 'Path exists.' }$null = $dirInfo.GetDirectories()$Path.Действительный путь:
Test-NetworkPath '\\ValidServer\C$\ValidFolder'
Выход:
Path exists.
Неверная папка:
Test-NetworkPath '\\ValidServer\C$\InvalidFolder'
Выход:
Path does not exist.
Directory not found.
Несуществующий сервер (ошибка сети):
Test-NetworkPath '\\InvalidServer\C$\SomeFolder'
Выход:
Path does not exist.
Path is inaccessible, likely due to network issues.
Да, это именно то, что я искал! Я пытался инициировать эти типы тонких сообщений об ошибках с помощью Get-Item и Get-ChildItem, но эти командлеты имеют много встроенной отказоустойчивости, которая мне не нужна (например, если -Path имеет значение null или пусто, это будет по умолчанию используется текущее местоположение, что в моем случае дает неправильный возврат и т. д.) Большое спасибо за помощь!
Одно из улучшений, которое я обнаружил, заключается в том, что [IO.DirectoryInfo]::New() действительно будет работать с путями длиной более 246 символов и находить путь, но .Exists по-прежнему будет сообщать ложь, потому что он слишком длинный. Поэтому я добавил раздел if ($Path.Length -gt 246){#use Get-Item here на всякий случай} и удалил исключение слишком длинного пути. Одна интересная вещь: -Path $Null по-прежнему говорит «недопустимые символы». Для меня «Доступ запрещен» вызывает исключение System.Management.Automation.MethodInvocationException, а не SecurityException.
@TanakaSaito, это странно! Я не проверял эти сценарии и в основном использовал информацию, найденную здесь. Но с другой стороны, это не совсем удивительно. Я придумал System.IO.IOException для сети так: я попробовал несуществующий сервер, и это выдало ошибку. Кроме того, теперь, когда я об этом думаю, я специально поставил System.IO.IOException последним, PathTooLongException наследуется от него. Не проверял, но предполагаю, что порядок важен.
Я думал, что найти информацию о том, почему вы получаете исключение MethodInvocationException, будет легко, но пока это не так. Но, как ни странно, поиск его без «PowerShell» по-прежнему вызывает множество проблем, связанных с PowerShell. Заставляет меня задуматься, является ли фактическим источником PowerShell, а не DirectoryInfo или GetDirectories, но я не понимаю, как это могло быть. Если я найду время сегодня, я мог бы попробовать несколько экспериментов и посмотреть, получу ли я ту же ошибку.
Возможно, я сказал слишком рано: категория ошибки — MethodInvoctionException, но полный идентификатор ошибки — UnauthorizedAccessException, что имеет гораздо больше смысла.
Как удаленный компьютер узнает о «пути, который существует, но не может быть доступен из-за проблем с сетью», если он не может получить к нему доступ? Если возникла проблема с сетью, например, маршрутизатор не работает и путь недоступен, сможет ли этот удаленный компьютер каким-то образом получить доступ к некоему магическому кешу всех путей, которые когда-то были ему доступны, и предположить, что этот путь все еще существует, и предложить этот другой путь? сообщение об ошибке? Я действительно пытаюсь понять, как это возможно.