Ошибка при вызове стороннего исполняемого файла из Powershell при использовании IDE
У меня есть PowerShell script, который использует du.exe(Использование диска из Sysinternals), чтобы рассчитать размер каталогов.
Если я запускаю du c:\Backup
в консоли, он работает так, как ожидалось, но одна и та же строка кода, запущенная в ISE или PowerGui, дает ожидаемый результат плюс ошибку
+ du <<<< c:\backup
+ CategoryInfo : NotSpecified: (:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
Почему? Как избежать этой ошибки? Я попытался вызвать выражение, используя &
, но не уходи.
Спасибо за помощь.
Ответы
Ответ 1
Чтобы избежать этого, вы можете перенаправить stderr на нуль, например:
du 2> $null
По сути, консольный хост и ISE (а также удаленный доступ) обрабатывают поток stderr по-разному. На консольном хосте важно, чтобы PowerShell поддерживал такие приложения, как edit.com, для работы вместе с другими приложениями, которые пишут цветной вывод и ошибки на экране. Если поток ввода-вывода не перенаправляется на консольный хост, PowerShell предоставляет собственный EXE-дескриптор консоли для записи напрямую. Это обходит PowerShell, поэтому PowerShell не видит, что есть ошибки, поэтому он не может сообщить об ошибке с помощью ошибки $или записи в поток PowerShell stderr.
ISE и удаленный доступ не нуждаются в поддержке этого сценария, поэтому они видят ошибки в stderr, а затем записывают ошибку и обновляют $error.
Ответ 2
Недавно я столкнулся с теми же проблемами, но мне хотелось бы получить выход stderr, предназначенный для stdout. Вы могли бы подумать, что следующее будет работать:
& du 2>&1
Но PowerShell будет интерпретировать перенаправление и обработать его после завершения 'du'. Обход, который я нашел, - это вызвать его с помощью cmd.exe/c:
& cmd /c 'du 2>&1'
Ответ 3
Другой способ подавить вывод NativeCommandError
- это преобразовать объекты в конвейер в строки, как описано ниже этот ответ:
du c:\Backup 2>&1 | %{ "$_" }
Ответ 4
Try:
du 2>&1 | %{ "$_" }
Ответ 5
Предыдущий FIX будет перенаправлять ошибки, но вы можете потерять реальную ошибку, если, например, ваше имя пользователя или пароль не подходит или если вы используете интегрированную проверку подлинности, у вас нет доступа.
Итак, вот способ реализации обработки ошибок и обход конкретной ошибки (то есть не одной), вызванной psexec.
try{
psexec command .....
}
catch [System.Management.Automation.RemoteException]{
if ($_.TargetObject -like "Connecting to *" -and $_.CategoryInfo.Category -eq "NotSpecified" -and $_.FullyQualifiedErrorId -eq "NativeCommandError" -and $_.InvocationInfo.MyCommand.Name -like "psexec*.exe"){
$error.Remove[$Error[0]]
}
else{
Throw
}
}
catch{
throw
}