Describe the bug
when using the admin powershell, after running the first command you get this error
Error reading or writing history file 'C:\windows\system32\config\systemprofile\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt': Access to the path 'C:\windows\syste
m32\config\systemprofile\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt' is denied.
but also its not remembering the history of commands being run
To Reproduce
Steps to reproduce the behavior:
- open up terminal
- right click and click ‘Admin powershell’
- run any powershell/cmd command e.g
net stats workstation
Expected behavior
not show this error, also remember powershell history?
Screenshots
If applicable, add screenshots to help explain your problem.
Server Software (please complete the following information):
- OS: [e.g. Ubuntu] Alpine
- Virtualization: [e.g. Docker] Docker
- Network: [e.g. LAN/WAN, reverse proxy, cloudflare, ssl offload, etc…] WAN, Traefik Proxy, Offload TLS
- Version: [e.g. 1.0.43] 1.0.51
- Node: [e.g. 18.4.0] 18.5.0
- Browser: [e.g. Google Chrome] Firefox
Remote Device (please complete the following information):
- Device: [e.g. Laptop] Computer
- OS: [e.g. Windows 10] Windows 10
- Version: [e.g. 21H2] 21H2
- Current Core Version (if known): [HINT: Go to a device then
console
Tab then typeinfo
]
Additional context
Add any other context about the problem here.
Your config.json file
N/A
The code looks like this:
foreach ($machine in $lbx_workstations.SelectedItems)
{
$temp = (get-winevent -computername $machine -FilterXML $commandString -ErrorAction SilentlyContinue -ErrorVariable eventerr|
Select MachineName, TimeCreated, LevelDisplayName, ID, ProviderName, Message)
blah blah blah...
I made a custom error variable, $eventerr, which works just fine when the get-winevent cmdlet can’t find any events that match the criteria in the XML commandstring. However, the problem is this: If the XML commandstring is invalid, the error is created in the $error variable instead of the $eventerr variable. I’d like to get that error stored in my custom error variable, but I don’t know where it is coming from or what is generating it. Or why it isn’t already in my custom variable, actually. When I look at these two different types of errors, this is the output I get:
PS C:\Temp> $error[0].fullyqualifiederrorid
System.Diagnostics.Eventing.Reader.EventLogException,Microsoft.PowerShell.Commands.GetWinEventCommand
PS C:\Temp> $error[1].fullyqualifiederrorid
NoMatchingEventsFound,Microsoft.PowerShell.Commands.GetWinEventCommand
I can catch the «NoMatchingEventsFound» error in the custom variable, but not the System.Diagnostics.Eventing… error.
Is there any way to get the «System.Diagnostics.Eventing… error into my custom error variable?
- Remove From My Forums
-
Вопрос
-
Добрый день , коллеги!
Проблема такая: есть скрипт
Param(
$tdir = «c:\*»)
$dir = get-item $tdir -exclude *.*
«————————————————————» >> FsDelOlderBackupDir.log
(get-date -format g).Tostring() + » Запуск процедуры…» >> FsDelOlderBackupDir.log
(get-date -format g).Tostring() + » Поиск самой старой папки…» >> FsDelOlderBackupDir.log
if($dir -eq $Null) {
(get-date -format g).Tostring() + » Папка пуста, удалять нечего » >> FsDelOlderBackupDir.log
}
elseif($dir -is [System.array]) {
$ct = $dir[0].creationtime
foreach($d in $dir) {
if($ct -ge $d.creationtime) {
$ct = $d.creationtime
$deldir = $d
}
}
(get-date -format g).Tostring() + » Самая старая папка » + $deldir.Tostring() >> FsDelOlderBackupDir.log
(get-date -format g).Tostring() + » Удаляю…» >> FsDelOlderBackupDir.log
Trap {«Перехвачена ошибка»}
remove-item $deldir -force -recurse
(get-date -format g).Tostring() + » Папка удалена» >> FsDelOlderBackupDir.log
}
else {
(get-date -format g).Tostring() + » В заданой директории всего одна папка, ничего не удаляем.» >> FsDelOlderBackupDir.log
}который в заданной папке каждый день отслеживает самую старую по дате папку и удаляет ее, проблема в том что в этой папке, а это сетевой ресурс с кучей подпапок и файлов, переодически юзеры создают множество вложенных папок и файлов с длинными именами, в
результате чего скрипт выдает ошибку типаRemove-Item : Слишком длинный путь или имя файла. Полное имя файла должно содержать меньше 260 знаков, а имя каталога —
меньше 248 знаков.
В J:\Документы\Scripts\FsDelOlderBackupDir.ps1:20 знак:12
+ remove-item <<<< $deldir -force -recurseзадача состоит в том чтобы перехватывать эту ошибку и ее текст вносить в логфайл и после продолжать удаление, то бишь чтоб он пропускал папки которые не может удалить, но при этом в логе оставлял записи о проблемных папках и файлах….
Ответы
-
>у меня ругается что не знает кто такой Try и Catch
try catch появились только во второй версии PoSh. А у вас какая?
>он же пойдет дальше по коду, следовательно операция Remove-Item на этом оборвется, так? А нужно чтоб она продолжалась
пойдет дальше выполнять remove-items для очередного элемента.
my blog: http://shserg.ru/
-
Помечено в качестве ответа
7 июня 2011 г. 13:20
-
Помечено в качестве ответа
-
Catch{Log($_
| out-string))}-
Помечено в качестве ответа
SteFFun
8 июня 2011 г. 13:33
-
Помечено в качестве ответа
-
Использовать переменную $error или как уже было выше сказано -ErrorVariable myerror ,и ошибки будут содержаться
в переменной $myerror.-
Помечено в качестве ответа
SteFFun
10 июня 2011 г. 8:32
-
Помечено в качестве ответа
-
Get-Item C:\Windows | Remove-Item -path {«$($_.fullname)\*»} -rec -fo
-
Помечено в качестве ответа
SteFFun
14 июня 2011 г. 8:29
-
Помечено в качестве ответа
В Powershell существует несколько уровней ошибок и несколько способов их обработать. Проблемы одного уровня (Non-Terminating Errors) можно решить с помощью привычных для Powershell команд. Другой уровень ошибок (Terminating Errors) решается с помощью исключений (Exceptions) стандартного, для большинства языков, блока в виде Try, Catch и Finally.
Как Powershell обрабатывает ошибки
До рассмотрения основных методов посмотрим на теоретическую часть.
Автоматические переменные $Error
В Powershell существует множество переменных, которые создаются автоматически. Одна из таких переменных — $Error хранит в себе все ошибки за текущий сеанс PS. Например так я выведу количество ошибок и их сообщение за весь сеанс:
Get-TestTest
$Error
$Error.Count
При отсутствии каких либо ошибок мы бы получили пустой ответ, а счетчик будет равняться 0:
Переменная $Error являет массивом и мы можем по нему пройтись или обратиться по индексу что бы найти нужную ошибку:
$Error[0]
foreach ($item in $Error){$item}
Свойства объекта $Error
Так же как и все что создается в Powershell переменная $Error так же имеет свойства (дополнительную информацию) и методы. Названия свойств и методов можно увидеть через команду Get-Member:
$Error | Get-Member
Например, с помощью свойства InvocationInfo, мы можем вывести более структурный отчет об ошибки:
$Error[0].InvocationInfo
Методы объекта $Error
Например мы можем очистить логи ошибок используя clear:
$Error.clear()
Критические ошибки (Terminating Errors)
Критические (завершающие) ошибки останавливают работу скрипта. Например это может быть ошибка в названии командлета или параметра. В следующем примере команда должна была бы вернуть процессы «svchost» дважды, но из-за использования несуществующего параметра ‘—Error’ не выполнится вообще:
'svchost','svchost' | % {Get-Process -Name $PSItem} --Error
Не критические ошибки (Non-Terminating Errors)
Не критические (не завершающие) ошибки не остановят работу скрипта полностью, но могут вывести сообщение об этом. Это могут быть ошибки не в самих командлетах Powershell, а в значениях, которые вы используете. На предыдущем примере мы можем допустить опечатку в названии процессов, но команда все равно продолжит работу:
'svchost111','svchost' | % {Get-Process -Name $PSItem}
Как видно у нас появилась информация о проблеме с первым процессом ‘svchost111’, так как его не существует. Обычный процесс ‘svchost’ он у нас вывелся корректно.
Параметр ErrorVariable
Если вы не хотите использовать автоматическую переменную $Error, то сможете определять свою переменную индивидуально для каждой команды. Эта переменная определяется в параметре ErrorVariable:
'svchost111','svchost' | % {Get-Process -Name $PSItem } -ErrorVariable my_err_var
$my_err_var
Переменная будет иметь те же свойства, что и автоматическая:
$my_err_var.InvocationInfo
Обработка некритических ошибок
У нас есть два способа определения последующих действий при ‘Non-Terminating Errors’. Это правило можно задать локально и глобально (в рамках сессии). Мы сможем полностью остановить работу скрипта или вообще отменить вывод ошибок.
Приоритет ошибок с $ErrorActionPreference
Еще одна встроенная переменная в Powershell $ErrorActionPreference глобально определяет что должно случится, если у нас появится обычная ошибка. По умолчанию это значение равно ‘Continue’, что значит «вывести информацию об ошибке и продолжить работу»:
$ErrorActionPreference
Если мы поменяем значение этой переменной на ‘Stop’, то поведение скриптов и команд будет аналогично критичным ошибкам. Вы можете убедиться в этом на прошлом скрипте с неверным именем процесса:
$ErrorActionPreference = 'Stop'
'svchost111','svchost' | % {Get-Process -Name $PSItem}
Т.е. скрипт был остановлен в самом начале. Значение переменной будет храниться до момента завершения сессии Powershell. При перезагрузке компьютера, например, вернется значение по умолчанию.
Ниже значение, которые мы можем установить в переменной $ErrorActionPreference:
- Continue — вывод ошибки и продолжение работы;
- Inquire — приостановит работу скрипта и спросит о дальнейших действиях;
- SilentlyContinue — скрипт продолжит свою работу без вывода ошибок;
- Stop — остановка скрипта при первой ошибке.
Самый частый параметр, который мне приходится использовать — SilentlyContinue:
$ErrorActionPreference = 'SilentlyContinue'
'svchost111','svchost' | % {Get-Process -Name $PSItem}
Использование параметра ErrorAction
Переменная $ErrorActionPreference указывает глобальный приоритет, но мы можем определить такую логику в рамках команды с параметром ErrorAction. Этот параметр имеет больший приоритет чем $ErrorActionPreference. В следующем примере, глобальная переменная определяет полную остановку скрипта, а в параметр ErrorAction говорит «не выводить ошибок и продолжить работу»:
$ErrorActionPreference = 'Stop'
'svchost111','svchost' | % {Get-Process -Name $PSItem -ErrorAction 'SilentlyContinue'}
Кроме ‘SilentlyContinue’ мы можем указывать те же параметры, что и в переменной $ErrorActionPreference.
Значение Stop, в обоих случаях, делает ошибку критической.
Обработка критических ошибок и исключений с Try, Catch и Finally
Когда мы ожидаем получить какую-то ошибку и добавить логику нужно использовать Try и Catch. Например, если в вариантах выше мы определяли нужно ли нам отображать ошибку или останавливать скрипт, то теперь сможем изменить выполнение скрипта или команды вообще. Блок Try и Catch работает только с критическими ошибками и в случаях если $ErrorActionPreference или ErrorAction имеют значение Stop.
Например, если с помощью Powershell мы пытаемся подключиться к множеству компьютеров один из них может быть выключен — это приведет к ошибке. Так как эту ситуацию мы можем предвидеть, то мы можем обработать ее. Процесс обработки ошибок называется исключением (Exception).
Синтаксис и логика работы команды следующая:
try {
# Пытаемся подключиться к компьютеру
}
catch [Имя исключения 1],[Имя исключения 2]{
# Раз компьютер не доступен, сделать то-то
}
finally {
# Блок, который выполняется в любом случае последним
}
Блок try мониторит ошибки и если она произойдет, то она добавится в переменную $Error и скрипт перейдет к блоку Catch. Так как ошибки могут быть разные (нет доступа, нет сети, блокирует правило фаервола и т.д.) то мы можем прописывать один блок Try и несколько Catch:
try {
# Пытаемся подключится
}
catch ['Нет сети']['Блокирует фаервол']{
# Записываем в файл
}
catch ['Нет прав на подключение']{
# Подключаемся под другим пользователем
}
Сам блок finally — не обязательный и используется редко. Он выполняется самым последним, после try и catch и не имеет каких-то условий.
Catch для всех типов исключений
Как и было показано выше мы можем использовать блок Catch для конкретного типа ошибок, например при проблемах с доступом. Если в этом месте ничего не указывать — в этом блоке будут обрабатываться все варианты ошибок:
try {
'svchost111','svchost' | % {Get-Process -Name $PSItem -ErrorAction 'Stop'}
}
catch {
Write-Host "Какая-то неисправность" -ForegroundColor RED
}
Такой подход не рекомендуется использовать часто, так как вы можете пропустить что-то важное.
Мы можем вывести в блоке catch текст ошибки используя $PSItem.Exception:
try {
'svchost111','svchost' | % {Get-Process -Name $PSItem -ErrorAction 'Stop'}
}
catch {
Write-Host "Какая-то неисправность" -ForegroundColor RED
$PSItem.Exception
}
Переменная $PSItem хранит информацию о текущей ошибке, а глобальная переменная $Error будет хранит информацию обо всех ошибках. Так, например, я выведу одну и ту же информацию:
$Error[0].Exception
Создание отдельных исключений
Что бы обработать отдельную ошибку сначала нужно найти ее имя. Это имя можно увидеть при получении свойств и методов у значения переменной $Error:
$Error[0].Exception | Get-Member
Так же сработает и в блоке Catch с $PSItem:
Для вывода только имени можно использовать свойство FullName:
$Error[0].Exception.GetType().FullName
Далее, это имя, мы вставляем в блок Catch:
try {
'svchost111','svchost' | % {Get-Process -Name $PSItem -ErrorAction 'Stop'}
}
catch [Microsoft.PowerShell.Commands.ProcessCommandException]{
Write-Host "Произошла ошибка" -ForegroundColor RED
$PSItem.Exception
}
Так же, как и было описано выше мы можем усложнять эти блоки как угодно указывая множество исключений в одном catch.
Выброс своих исключений
Иногда нужно создать свои собственные исключения. Например мы можем запретить добавлять через какой-то скрипт названия содержащие маленькие буквы или сотрудников без указания возраста и т.д. Способов создать такие ошибки — два и они тоже делятся на критические и обычные.
Выброс с throw
Throw — выбрасывает ошибку, которая останавливает работу скрипта. Этот тип ошибок относится к критическим. Например мы можем указать только текст для дополнительной информации:
$name = 'AD.1'
if ($name -match '.'){
throw 'Запрещено использовать точки в названиях'
}
Если нужно, то мы можем использовать исключения, которые уже были созданы в Powershell:
$name = 'AD.1'
if ($name -like '*.*'){
throw [System.IO.FileNotFoundException]'Запрещено использовать точки в названиях'
}
Использование Write-Error
Команда Write-Error работает так же, как и ключ ErrorAction. Мы можем просто отобразить какую-то ошибку и продолжить выполнение скрипта:
$names = @('CL1', 'AD.1', 'CL3')
foreach ($name in $names){
if ($name -like '*.*'){
Write-Error -Message 'Обычная ошибка'
}
else{
$name
}
}
При необходимости мы можем использовать параметр ErrorAction. Значения этого параметра были описаны выше. Мы можем указать значение ‘Stop’, что полностью остановит выполнение скрипта:
$names = @('CL1', 'AD.1', 'CL3')
foreach ($name in $names){
if ($name -like '*.*'){
Write-Error -Message 'Обычная ошибка' -ErrorAction 'Stop'
}
else{
$name
}
}
Отличие команды Write-Error с ключом ErrorAction от обычных команд в том, что мы можем указывать исключения в параметре Exception:
Write-Error -Message 'Обычная ошибка' -ErrorAction 'Stop'
Write-Error -Message 'Исключение' -Exception [System.IO.FileNotFoundException] -ErrorAction 'Stop'
В Exception мы так же можем указывать сообщение. При этом оно будет отображаться в переменной $Error:
Write-Error -Exception [System.IO.FileNotFoundException]'Моё сообщение'
…
Теги:
#powershell
#ошибки
У меня только что был установлен PS 7.0.2 на 2 компьютерах с RHEL 7.x (maipo). Как ни странно, один из них показывает следующую ошибку
$ pwsh
PS /home/user_name> dir
Error reading or writing history file '/home/user_name/.local/share/powershell/PSReadLine/Console_history.txt': Access to the path '/home/user_name/.local/share/powershell/PSReadLine/Console_history.txt' is denied
PS /home/user_name> exit
Error reading or writing history file '/home/user_name/.local/share/powershell/PSReadLine/Console_history.txt': Access to the path '/home/user_name/.local/share/powershell/PSReadLine/Console_history.txt' is denied
This error will not be reported again in this session. Consider using a different path with:
Set-PSReadLineOption -HistorySavePath <Path>
Or not saving history with:
Set-PSReadLineOption -HistorySaveStyle SaveNothing
Я не могу понять почему. Все, что я сделал, это загрузил RPM и установил его. И оба ящика практически копии друг друга:(
Какие-либо предложения?