Ошибка чтения или записи файла журнала powershell

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:

  1. open up terminal
  2. right click and click ‘Admin powershell’
  3. 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 type info]

Additional context
Add any other context about the problem here.

Your config.json file
N/A

Hmm… I tried to repro, but this time repro’ed a different «access denied» problem.

My repro steps were:

  1. Using Hyper-V «Quick Create», create an Ubuntu 18.04.3 LTS virtual machine.
  2. In the VM, download the RC1 .deb file for Ubuntu 18.04.
  3. Install the MS GPG keys, and then install the .deb according to the «direct download» instructions.
  4. sudo bash so that the first run of pwsh would be as the root user.
  5. pwsh-preview and then run dir.

Expected result: it all works.
Actual result: an «access denied error: «Get-ChildItem: Access to the path ‘/home/dt29/shared-drives’ is denied.»

But that isn’t what this Issue is about, and could be unrelated. So I continued with my repro.
6. exit the instance of pwsh-preview being run as root.
7. exit the instance of bash being run as root.
8. Now I’m back to my normal user account shell, and I run pwsh-preview again as a normal user.
9. Finally, I run dir.

Expected result: it all works; no errors.
Actual result: I get an «access denied» error accessing the PSReadLine history file, and then as an added bonus, the rest of the output of dir stays red.

I don’t know if the original repro by @MaximoTrinidad used different repro steps. Perhaps his problem was unrelated, and has been fixed. But my problem—where if the first time you run pwsh, you run as root, and then permissions are messed up for the normal user—is unchanged.

And of course, note that the «real» reason that I end up in this situation is not because I manually switch to the superuser for the first run, but because I have a bootstrapping/setup script that I run, which does many privileged things (like installing software), so it’s run as root, of course, and it also runs PowerShell scripts (once PowerShell is installed), also of course. :)

Full ouput:

To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
dt29@danthom-tmp:~$ pwsh
Command 'pwsh' not found, but can be installed with:
sudo snap install powershell
dt29@danthom-tmp:~$ pwsh-preview
Command 'pwsh-preview' not found, but can be installed with:
sudo snap install powershell-preview
dt29@danthom-tmp:~$ wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb
dt29@danthom-tmp:~$ sudo dpkg -i packages-microsoft-prod.deb
[sudo] password for dt29: 
Selecting previously unselected package packages-microsoft-prod.
(Reading database ... 131513 files and directories currently installed.)
Preparing to unpack packages-microsoft-prod.deb ...
Unpacking packages-microsoft-prod (1.0-ubuntu18.04.2) ...
Setting up packages-microsoft-prod (1.0-ubuntu18.04.2) ...
dt29@danthom-tmp:~$ sudo apt-get update
Get:1 https://packages.microsoft.com/ubuntu/18.04/prod bionic InRelease [4,003 B]
Get:2 http://security.ubuntu.com/ubuntu bionic-security InRelease [88.7 kB]    
Hit:3 http://archive.ubuntu.com/ubuntu bionic InRelease                        
Get:4 https://packages.microsoft.com/ubuntu/18.04/prod bionic/main amd64 Packages [85.3 kB]
Get:5 http://archive.ubuntu.com/ubuntu bionic-updates InRelease [88.7 kB]      
Get:6 http://security.ubuntu.com/ubuntu bionic-security/main amd64 Packages [593 kB]
Get:7 http://archive.ubuntu.com/ubuntu bionic-backports InRelease [74.6 kB]    
Get:8 http://archive.ubuntu.com/ubuntu bionic/main amd64 DEP-11 Metadata [477 kB]
Get:9 http://security.ubuntu.com/ubuntu bionic-security/main Translation-en [194 kB]
Get:10 http://security.ubuntu.com/ubuntu bionic-security/main amd64 DEP-11 Metadata [38.5 kB]
Get:11 http://security.ubuntu.com/ubuntu bionic-security/main DEP-11 48x48 Icons [17.6 kB]
Get:12 http://security.ubuntu.com/ubuntu bionic-security/main DEP-11 64x64 Icons [41.4 kB]
Get:13 http://security.ubuntu.com/ubuntu bionic-security/restricted amd64 Packages [15.1 kB]
Get:14 http://security.ubuntu.com/ubuntu bionic-security/restricted Translation-en [4,684 B]
Get:15 http://security.ubuntu.com/ubuntu bionic-security/universe amd64 Packages [627 kB]
Get:16 http://archive.ubuntu.com/ubuntu bionic/main DEP-11 48x48 Icons [118 kB]
Get:17 http://archive.ubuntu.com/ubuntu bionic/main DEP-11 64x64 Icons [245 kB]
Get:18 http://archive.ubuntu.com/ubuntu bionic/universe amd64 Packages [8,570 kB]
Get:19 http://security.ubuntu.com/ubuntu bionic-security/universe Translation-en [210 kB]
Get:20 http://security.ubuntu.com/ubuntu bionic-security/universe amd64 DEP-11 Metadata [42.2 kB]
Get:21 http://security.ubuntu.com/ubuntu bionic-security/universe DEP-11 48x48 Icons [16.4 kB]
Get:22 http://security.ubuntu.com/ubuntu bionic-security/universe DEP-11 64x64 Icons [113 kB]
Get:23 http://security.ubuntu.com/ubuntu bionic-security/multiverse amd64 Packages [6,120 B]
Get:24 http://security.ubuntu.com/ubuntu bionic-security/multiverse Translation-en [2,600 B]
Get:25 http://security.ubuntu.com/ubuntu bionic-security/multiverse amd64 DEP-11 Metadata [2,464 B]
Get:26 http://security.ubuntu.com/ubuntu bionic-security/multiverse DEP-11 48x48 Icons [29 B]
Get:27 http://security.ubuntu.com/ubuntu bionic-security/multiverse DEP-11 64x64 Icons [2,638 B]
Get:28 http://archive.ubuntu.com/ubuntu bionic/universe Translation-en [4,941 kB]
Get:29 http://archive.ubuntu.com/ubuntu bionic/universe amd64 DEP-11 Metadata [3,287 kB]
Get:30 http://archive.ubuntu.com/ubuntu bionic/universe DEP-11 48x48 Icons [2,151 kB]
Get:31 http://archive.ubuntu.com/ubuntu bionic/universe DEP-11 64x64 Icons [8,420 kB]
Get:32 http://archive.ubuntu.com/ubuntu bionic/multiverse amd64 Packages [151 kB]
Get:33 http://archive.ubuntu.com/ubuntu bionic/multiverse Translation-en [108 kB]
Get:34 http://archive.ubuntu.com/ubuntu bionic/multiverse amd64 DEP-11 Metadata [49.7 kB]
Get:35 http://archive.ubuntu.com/ubuntu bionic/multiverse DEP-11 48x48 Icons [8,931 B]
Get:36 http://archive.ubuntu.com/ubuntu bionic/multiverse DEP-11 64x64 Icons [225 kB]
Get:37 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 Packages [817 kB]
Get:38 http://archive.ubuntu.com/ubuntu bionic-updates/main Translation-en [288 kB]
Get:39 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 DEP-11 Metadata [294 kB]
Get:40 http://archive.ubuntu.com/ubuntu bionic-updates/main DEP-11 48x48 Icons [73.8 kB]
Get:41 http://archive.ubuntu.com/ubuntu bionic-updates/main DEP-11 64x64 Icons [143 kB]
Get:42 http://archive.ubuntu.com/ubuntu bionic-updates/restricted amd64 Packages [24.1 kB]
Get:43 http://archive.ubuntu.com/ubuntu bionic-updates/restricted Translation-en [6,620 B]
Get:44 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 Packages [1,033 kB]
Get:45 http://archive.ubuntu.com/ubuntu bionic-updates/universe Translation-en [319 kB]
Get:46 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 DEP-11 Metadata [264 kB]
Get:47 http://archive.ubuntu.com/ubuntu bionic-updates/universe DEP-11 48x48 Icons [203 kB]
Get:48 http://archive.ubuntu.com/ubuntu bionic-updates/universe DEP-11 64x64 Icons [458 kB]
Get:49 http://archive.ubuntu.com/ubuntu bionic-updates/multiverse amd64 Packages [9,284 B]
Get:50 http://archive.ubuntu.com/ubuntu bionic-updates/multiverse Translation-en [4,508 B]
Get:51 http://archive.ubuntu.com/ubuntu bionic-updates/multiverse amd64 DEP-11 Metadata [2,464 B]
Get:52 http://archive.ubuntu.com/ubuntu bionic-updates/multiverse DEP-11 48x48 Icons [29 B]
Get:53 http://archive.ubuntu.com/ubuntu bionic-updates/multiverse DEP-11 64x64 Icons [2,638 B]
Get:54 http://archive.ubuntu.com/ubuntu bionic-backports/main amd64 Packages [2,512 B]
Get:55 http://archive.ubuntu.com/ubuntu bionic-backports/main Translation-en [1,644 B]
Get:56 http://archive.ubuntu.com/ubuntu bionic-backports/universe amd64 Packages [4,028 B]
Get:57 http://archive.ubuntu.com/ubuntu bionic-backports/universe Translation-en [1,856 B]
Get:58 http://archive.ubuntu.com/ubuntu bionic-backports/universe amd64 DEP-11 Metadata [7,976 B]
Get:59 http://archive.ubuntu.com/ubuntu bionic-backports/universe DEP-11 48x48 Icons [29 B]
Get:60 http://archive.ubuntu.com/ubuntu bionic-backports/universe DEP-11 64x64 Icons [29 B]
Fetched 35.0 MB in 8s (4,429 kB/s)                                             
Reading package lists... Done
dt29@danthom-tmp:~$ sudo add-apt-repository universe
'universe' distribution component is already enabled for all sources.
dt29@danthom-tmp:~$ sudo dpkg -i Downloads/powershell-preview_7.0.0-rc.1-1.ubuntu.18.04_amd64.deb 
Selecting previously unselected package powershell-preview.
(Reading database ... 131521 files and directories currently installed.)
Preparing to unpack .../powershell-preview_7.0.0-rc.1-1.ubuntu.18.04_amd64.deb ...
Unpacking powershell-preview (7.0.0-rc.1-1.ubuntu.18.04) ...
dpkg: dependency problems prevent configuration of powershell-preview:
powershell-preview depends on liblttng-ust0; however:
Package liblttng-ust0 is not installed.
dpkg: error processing package powershell-preview (--install):
dependency problems - leaving unconfigured
Processing triggers for man-db (2.8.3-2ubuntu0.1) ...
Errors were encountered while processing:
powershell-preview
dt29@danthom-tmp:~$ sudo apt-get install -f
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Correcting dependencies... Done
The following packages were automatically installed and are no longer required:
app-install-data apt-clone archdetect-deb btrfs-tools cryptsetup-bin
device-tree-compiler dmeventd dmraid dpkg-repack gir1.2-timezonemap-1.0
gir1.2-xkl-1.0 grub-pc-bin kpartx kpartx-boot libdebian-installer4
libdevmapper-event1.02.1 libdmraid1.0.0.rc16 libido3-0.1-0 liblvm2app2.2
liblvm2cmd2.02 libreadline5 libtimezonemap-data libtimezonemap1 lvm2
python3-icu python3-pam rdate u-boot-tools
Use 'sudo apt autoremove' to remove them.
The following additional packages will be installed:
liblttng-ust-ctl4 liblttng-ust0 liburcu6
The following NEW packages will be installed:
liblttng-ust-ctl4 liblttng-ust0 liburcu6
0 upgraded, 3 newly installed, 0 to remove and 229 not upgraded.
1 not fully installed or removed.
Need to get 287 kB of archives.
After this operation, 1,348 kB of additional disk space will be used.
Do you want to continue? [Y/n] y
Get:1 http://archive.ubuntu.com/ubuntu bionic/main amd64 liburcu6 amd64 0.10.1-1 [52.1 kB]
Get:2 http://archive.ubuntu.com/ubuntu bionic/universe amd64 liblttng-ust-ctl4 amd64 2.10.1-1 [80.8 kB]
Get:3 http://archive.ubuntu.com/ubuntu bionic/universe amd64 liblttng-ust0 amd64 2.10.1-1 [154 kB]
Fetched 287 kB in 1s (206 kB/s)        
Selecting previously unselected package liburcu6:amd64.
(Reading database ... 132140 files and directories currently installed.)
Preparing to unpack .../liburcu6_0.10.1-1_amd64.deb ...
Unpacking liburcu6:amd64 (0.10.1-1) ...
Selecting previously unselected package liblttng-ust-ctl4:amd64.
Preparing to unpack .../liblttng-ust-ctl4_2.10.1-1_amd64.deb ...
Unpacking liblttng-ust-ctl4:amd64 (2.10.1-1) ...
Selecting previously unselected package liblttng-ust0:amd64.
Preparing to unpack .../liblttng-ust0_2.10.1-1_amd64.deb ...
Unpacking liblttng-ust0:amd64 (2.10.1-1) ...
Setting up liburcu6:amd64 (0.10.1-1) ...
Setting up liblttng-ust-ctl4:amd64 (2.10.1-1) ...
Setting up liblttng-ust0:amd64 (2.10.1-1) ...
Setting up powershell-preview (7.0.0-rc.1-1.ubuntu.18.04) ...
Processing triggers for libc-bin (2.27-3ubuntu1) ...
dt29@danthom-tmp:~$ sudo bash
root@danthom-tmp:~# whoami
root
root@danthom-tmp:~# pwsh-preview
PowerShell 7.0.0-rc.1
Copyright (c) Microsoft Corporation. All rights reserved.
https://aka.ms/powershell
Type 'help' to get help.
PS /home/dt29> dir
Get-ChildItem: Access to the path '/home/dt29/shared-drives' is denied.
PS /home/dt29> exit
root@danthom-tmp:~# exit
exit
dt29@danthom-tmp:~$ pwsh-preview
PowerShell 7.0.0-rc.1
Copyright (c) Microsoft Corporation. All rights reserved.
https://aka.ms/powershell
Type 'help' to get help.
PS /home/dt29> dir
Error reading or writing history file '/home/dt29/.local/share/powershell/PSReadLine/ConsoleHost_history.txt': Access to the path '/home/dt29/.local/share/powershell/PSReadLine/ConsoleHost_history.txt' is denied.
ưm
Directory: /home/dt29
Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----            1/3/2020  2:34 PM                Desktop
d----            1/3/2020  2:34 PM                Documents
d----            1/3/2020  2:35 PM                Downloads
d----            1/3/2020  2:34 PM                Music
d----            1/3/2020  2:34 PM                Pictures
d----            1/3/2020  2:34 PM                Public
d-r--          12/31/1969  4:00 PM                shared-drives
d----            1/3/2020  2:34 PM                Templates
d----            1/3/2020  2:34 PM                Videos
-----            1/3/2020  2:32 PM           8980 examples.desktop
-----            1/2/2019  3:49 PM           3132 packages-microsoft-prod.deb
PS /home/dt29> 

And a screenshot of the last error, showing the red text:
image

  • 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:ДокументыScriptsFsDelOlderBackupDir.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

У меня только что был установлен PS 7.0.2 на 2x компьютерах под управлением 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 и установил его. И оба ящика практически копии друг друга :(

Какие-либо предложения?

1 ответ

Лучший ответ

Эээ .. только что разобрался. Это была ошибочная настройка umask, переопределяющая значение по умолчанию в моем ~ / .bashrc.

Комментирование решило проблему.


0

Mayuresh K
29 Июн 2020 в 11:30

I wasn’t satisfied with any answer I was finding, so I mixed a few and came up with this (in PowerShell 3.0+):

$output = try{your_command *>&1}catch{$_}

With this you can capture all errors and output that are generated by trying to use your_command.

It catches exceptions when you use a non-existent command:

PS C:Usersjdgregson> $output = try{your_command *>&1}catch{$_}
PS C:Usersjdgregson> echo $output
your_command : The term 'your_command' is not recognized as the name of a
cmdlet, function, script file, or operable program. Check the spelling of the
name, or if a path was included, verify that the path is correct and try again.
At line:1 char:15
+ $output = try{your_command 2>&1}catch{$_}
+               ~~~~~~~~~~~~
+ CategoryInfo          : ObjectNotFound: (your_command:String) [], Comman
dNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
PS C:Usersjdgregson>

It catches exceptions when you pass invalid arguments to an existing command:

PS C:Usersjdgregson> $output = try{cat C:invalid-path.txt *>&1}catch{$_}
PS C:Usersjdgregson> echo $output
cat : Cannot find path 'C:invalid-path.txt' because it does not exist.
At line:1 char:15
+ $output = try{cat C:invalid-path.txt 2>&1}catch{$_}
+               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : ObjectNotFound: (C:invalid-path.txt:String) [Ge
t-Content], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetCo
ntentCommand

And it catches the output if there was no problem with your command at all:

PS C:Usersjdgregson> $output = try{cat C:valid-path.txt *>&1}catch{$_}
PS C:Usersjdgregson> echo $output
this file is really here

It works for your example too:

PS C:Usersjdgregson> $output = try{Test-Error *>&1}catch{$_}
PS C:Usersjdgregson> echo $output
echo
WARNING: warning
Test-Error : error
At line:1 char:15
+ $output = try{Test-Error *>&1}catch{$_}
+               ~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorExcep
tion
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorExceptio
n,Test-Error

Журнал событий Windows (Event Log) — это важный инструмент, который позволяет администратору отслеживать ошибки, предупреждения и другие информационные сообщения, которые регистрируются операционной системой, ее компонентами и различными программами. Для просмотра журнала событий Windows можно использовать графическую MMC оснастку Event Viewer (
eventvwr.msc
). В некоторых случаях для поиска информации в журналах событий и их анализа гораздо удобнее использовать PowerShell. В этой статье мы покажем, как получать информацию из журналов событий Windows с помощью командлета Get-WinEvent.

Содержание:

  • Получение логов Windows с помощью Get-WinEvent
  • Get-WinEvent: быстрый поиск в событиях Event Viewer с помощью FilterHashtable
  • Расширенный фильтры событий Get-WinEvent с помощью FilterXml
  • Получить логи Event Viewer с удаленных компьютеров

На данный момент в Windows доступны два командлета для доступа к событиям в Event Log: Get-EventLog и Get-WinEvent. В подавляющем большинстве случаев рекомендуем использовать именно Get-WinEvent, т.к. он более производителен, особенно в сценариях обработки большого количества событий с удаленных компьютеров. Командлет Get-EventLog является устаревшим и использовался для получения логов в более ранних версиях Windows. Кроме того, Get-EventLog не поддерживается в современных версиях PowerShell Core 7.x.

Получение логов Windows с помощью Get-WinEvent

Для использования команды Get-WinEvent нужно запустить PowerShell с правами администратора (при запуске Get-WinEvent от имени пользователя вы не сможете получить доступ к некоторым логам, например, к Security).

Для получения списка событий из определенного журнала, нужно указать его имя. В данном примере мы выведем последние 20 событий из журнала System:

Get-WinEvent -LogName Application -MaxEvents 20

Чаще всего вам нужно будет получать информацию из журналов System, Application, Security или Setup. Но вы можете указать и другие журналы. Полный список журналов событий в Windows можно получить с помощью команды:

Get-WinEvent -ListLog *

Get-WinEvent командлет PowerShell

Например, чтобы вывести события RDP подключений к компьютеру, нужно указать лог Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational:

Get-WinEvent -LogName Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational

Или получить логи SSH подключений к Windows из журнала OpenSSH/Operational:

Get-WinEvent -LogName OpenSSH/Operational

Можно выбрать события сразу из нескольких журналов. Например, чтобы получить информацию о ошибках и предупреждениях из журналов System и Application за последние 24 часа (сутки), можно использовать такой код:

$StartDate = (Get-Date) - (New-TimeSpan -Day 1)
Get-WinEvent Application,System | Where-Object {($_.LevelDisplayName -eq "Error" -or $_.LevelDisplayName -eq "Warning") -and ($_.TimeCreated -ge $StartDate )}

Get-WinEvent командлет для поиска событий в журнале Windows

Чтобы вывести только определенные поля событий, можно использовать Select-Object или Format-Table:

Get-WinEvent -LogName System | Format-Table Machinename, TimeCreated, Id, UserID

Get-WinEvent вывести определенные поля событий

Можно выполнить дополнительные преобразования с полученными данными. Например, в этом примере мы сразу преобразуем имя пользователя в SID:

Get-WinEvent -filterhash @{Logname = 'system'} |
Select-Object @{Name="Computername";Expression = {$_.machinename}},@{Name="UserName";Expression = {$_.UserId.translate([System.Security.Principal.NTAccount]).value}}, TimeCreated

Get-WinEvent: быстрый поиск в событиях Event Viewer с помощью FilterHashtable

Рассмотренный выше способ выбора определенных событий из журналов Event Viewer с помощью Select-Object прост для понимая, но выполняется крайне медленно. Это особенно заметно при выборке большого количества событий. В большинстве случаев для выборки событий нужно использовать фильтрацию на стороне службы Event Viewer с помощью параметра FilterHashtable.

Попробуем сформировать список ошибок и предупреждений за 30 дней с помощью Where-Object и FilterHashtable. Сравнима скорость выполнения этих двух команд PowerShell с помощью Measure-Command:

$StartDate = (Get-Date).AddDays(-30)

Проверим скорость выполнения команды с Where-Object:

(Measure-Command {Get-WinEvent Application,System | Where-Object {($_.LevelDisplayName -eq "Error" -or $_.LevelDisplayName -eq "Warning") -and ($_.TimeCreated -ge $StartDate )}}).TotalMilliseconds

Аналогичная команда с FilterHashtable:

(Measure-Command {Get-WinEvent -FilterHashtable @{LogName = 'System','Application'; Level =2,3; StartTime=$StartDate }})..TotalMilliseconds

В данном примере видно, что команда выборки событий через FilterHashtable выполняется в 30 раз быстрее, чем если бы обычный Where-Object (
2.5
сек vs
76
секунд).

Get-WinEvent FilterHashtable выполняется намного быстрее

Если вам нужно найти события по EventID, используйте следующую команду с FilterHashtable:

Get-WinEvent -FilterHashtable @{logname='System';id=1074}|ft TimeCreated,Id,Message

В параметре FilterHashtable можно использовать фильтры по следующим атрибутам событий:

  • LogName
  • ProviderName
  • Path
  • Keywords (для поиска успешных событий нужно использовать значение 9007199254740992 или для неуспешных попыток 4503599627370496)
  • ID
  • Level (1=FATAL, 2=ERROR, 3=Warning, 4=Information, 5=DEBUG, 6=TRACE, 0=Info)
  • StartTime
  • EndTime
  • UserID (SID пользователя)
  • Data

Пример поиска события за определенный промежуток времени:

Get-WinEvent -FilterHashTable @{LogName='System'; StartTime=(get-date).AddDays(-7); EndTime=(get-date).AddHours(-1); ID=1234}

Если нужно найти определенный текст в описании события, можно использовать такую команду:

Get-WinEvent -FilterHashtable @{logname='System'}|Where {$_.Message -like "*USB*"}

Get-WinEvent поиск текста в событиях

Расширенный фильтры событий Get-WinEvent с помощью FilterXml

Фильтры Get-WinEvent с параметром FilterHashtable являются несколько ограниченными. Если вам нужно использовать для выборки событий сложные запросы с множеством условий, нужно использовать параметр FilterXml, который позволяет сформировать запрос на выбор событий в Event Viewer с помощью XML запроса. Как и FilterHashtable, фильтры FilterXml выполняется на стороне сервера, поэтому результат вы получите довольно быстро.

Например, аналогичный запрос для получения последних ошибок из журнала System за последние 30 дней может выглядеть так:

$xmlQuery = @'
<QueryList>
<Query Id="0" Path="System">
<Select Path="System">*[System[(Level=2 or Level=3) and TimeCreated[timediff(@SystemTime) &lt;= 2592000000]]]</Select>
</Query>
</QueryList>
'@
Get-WinEvent -FilterXML $xmlQuery

Get-WinEvent -FilterXML

Для построения кода сложных XML запросов можно использовать графическую консоль Event Viewer:

  1. Запустите
    eventvwr.msc
    ;
  2. Найдите журнал для которого вы хотите создать и выберите Filter Current Log; Фильтр журнала событий Event Viewer
  3. Выберите необходимые параметры запроса в форме. В этом примере я хочу найти события с определенными EventID за последние 7 дней от определенного пользователя; формируем фильтр в Event Viewer
  4. Чтобы получить код XML запроса для параметра FilterXML, перейдите на вкладку XML и скопируйте полученный код (CTRL+A, CTRL+C); XML запрос в Event Viewer
  5. Если нужно, вы можете вручную отредактировать данный запрос.

Для экспорта списка событий в CSV файл нужно использовать командлет Export-CSV:

$Events= Get-WinEvent -FilterXML $xmlQuery
$events| Export-CSV "C:psFilterSYSEvents.csv" -NoTypeInformation -Encoding UTF8

Получить логи Event Viewer с удаленных компьютеров

Для получения события с удаленного компьютер достаточно указать его имя в параметре -ComputerName:

$computer='msk-dc01'
Get-WinEvent -ComputerName $computer -FilterHashtable @{LogName="System"; StartTime=(get-date).AddHours(-24)} |   select Message,Id,TimeCreated

Можно опросить сразу несколько серверов/компьютеров и поискать на них определенные события. Список серверов можно получить из текстового файла:

$servers = Get-Content -Path C:psservers.txt

Или из Active Directory:

$servers = (Get-ADComputer -Filter 'operatingsystem -like "*Windows server*" -and enabled -eq "true"').Name
foreach ($server in $servers) {
Get-WinEvent -ComputerName $server -MaxEvents 5 -FilterHashtable @{
LogName = 'System'; ID= 1234
} | Select-Object -Property ID, MachineName
}

Здесь есть другой пример для поиска событий блокировки учетной записи пользователя на всех контроллерах домена:

$Username = 'a.ivanov'
Get-ADDomainController -fi * | select -exp hostname | % {
$GweParams = @{
‘Computername’ = $_
‘LogName’ = ‘Security’
‘FilterXPath’ = "*[System[EventID=4740] and EventData[Data[@Name='TargetUserName']='$Username']]"
}
$Events = Get-WinEvent @GweParams
$Events | foreach {$_.Computer + " " +$_.Properties[1].value + ' ' + $_.TimeCreated}
}

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

Переменная $Error в Powershell

При отсутствии каких либо ошибок мы бы получили пустой ответ, а счетчик будет равняться 0:

Счетчик ошибок с переменной $Error в Powershell

Переменная $Error являет массивом и мы можем по нему пройтись или обратиться по индексу что бы найти нужную ошибку:

$Error[0]

foreach ($item in $Error){$item}

Вывод ошибки по индексу в Powershell c $Error

Свойства объекта $Error

Так же как и все что создается в Powershell переменная $Error так же имеет свойства (дополнительную информацию) и методы. Названия свойств и методов можно увидеть через команду Get-Member:

$Error | Get-Member

Свойства переменной $Error в Powershell

Например, с помощью свойства InvocationInfo, мы можем вывести более структурный отчет об ошибки:

$Error[0].InvocationInfo

Детальная информация об ошибке с $Error в Powershell

Методы объекта $Error

Например мы можем очистить логи ошибок используя clear:

$Error.clear()

Очистка логов об ошибке в Powershell с $Error

Критические ошибки (Terminating Errors)

Критические (завершающие) ошибки останавливают работу скрипта. Например это может быть ошибка в названии командлета или параметра. В следующем примере команда должна была бы вернуть процессы «svchost» дважды, но из-за использования несуществующего параметра ‘—Error’ не выполнится вообще:

'svchost','svchost' | % {Get-Process -Name $PSItem} --Error 

Критические ошибки в Powershell Terminating Errors

Не критические ошибки (Non-Terminating Errors)

Не критические (не завершающие) ошибки не остановят работу скрипта полностью, но могут вывести сообщение об этом. Это могут быть ошибки не в самих командлетах Powershell, а в значениях, которые вы используете. На предыдущем примере мы можем допустить опечатку в названии процессов, но команда все равно продолжит работу:

'svchost111','svchost' | % {Get-Process -Name $PSItem}

Не критические ошибки в Powershell Non-Terminating Errors

Как видно у нас появилась информация о проблеме с первым процессом ‘svchost111’, так как его не существует. Обычный процесс ‘svchost’ он у нас вывелся корректно.

Параметр ErrorVariable

Если вы не хотите использовать автоматическую переменную $Error, то сможете определять свою переменную индивидуально для каждой команды. Эта переменная определяется в параметре ErrorVariable:

'svchost111','svchost' | % {Get-Process -Name $PSItem } -ErrorVariable my_err_var
$my_err_var

Использование ErrorVariable в Powershell

Переменная будет иметь те же свойства, что и автоматическая:

$my_err_var.InvocationInfo

Свойства  ErrorVariable в Powershell

Обработка некритических ошибок

У нас есть два способа определения последующих действий при ‘Non-Terminating Errors’. Это правило можно задать локально и глобально (в рамках сессии). Мы сможем полностью остановить работу скрипта или вообще отменить вывод ошибок.

Приоритет ошибок с $ErrorActionPreference

Еще одна встроенная переменная в Powershell $ErrorActionPreference глобально определяет что должно случится, если у нас появится обычная ошибка. По умолчанию это значение равно ‘Continue’, что значит «вывести информацию об ошибке и продолжить работу»:

$ErrorActionPreference

Определение $ErrorActionPreference в Powershell

Если мы поменяем значение этой переменной на ‘Stop’, то поведение скриптов и команд будет аналогично критичным ошибкам. Вы можете убедиться в этом на прошлом скрипте с неверным именем процесса:

$ErrorActionPreference = 'Stop'
'svchost111','svchost' | % {Get-Process -Name $PSItem}

Определение глобальной переменной $ErrorActionPreference в Powershell

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

Ниже значение, которые мы можем установить в переменной $ErrorActionPreference:

  • Continue — вывод ошибки и продолжение работы;
  • Inquire — приостановит работу скрипта и спросит о дальнейших действиях;
  • SilentlyContinue — скрипт продолжит свою работу без вывода ошибок;
  • Stop — остановка скрипта при первой ошибке.

Самый частый параметр, который мне приходится использовать — SilentlyContinue:

$ErrorActionPreference = 'SilentlyContinue'
'svchost111','svchost' | % {Get-Process -Name $PSItem}

Игнорирование ошибок в Powershell с ErrorActionPreference и SilentlyContinue

Использование параметра ErrorAction

Переменная $ErrorActionPreference указывает глобальный приоритет, но мы можем определить такую логику в рамках команды с параметром ErrorAction. Этот параметр имеет больший приоритет чем $ErrorActionPreference. В следующем примере, глобальная переменная определяет полную остановку скрипта, а в параметр ErrorAction говорит «не выводить ошибок и продолжить работу»:

$ErrorActionPreference = 'Stop'
'svchost111','svchost' | % {Get-Process -Name $PSItem -ErrorAction 'SilentlyContinue'}

Использование параметра ErrorAction в ошибках с Powershell

Кроме ‘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
}

Игнорирование всех ошибок с try и catch в Powershell

Такой подход не рекомендуется использовать часто, так как вы можете пропустить что-то важное.

Мы можем вывести в блоке catch текст ошибки используя $PSItem.Exception:

try {
   'svchost111','svchost' | % {Get-Process -Name $PSItem -ErrorAction 'Stop'}
}
catch {
   Write-Host "Какая-то неисправность" -ForegroundColor RED
   $PSItem.Exception
}

Переменная PSITem в блоке try и catch в Powershell

Переменная $PSItem хранит информацию о текущей ошибке, а глобальная переменная $Error будет хранит информацию обо всех ошибках. Так, например, я выведу одну и ту же информацию:

$Error[0].Exception

Вывод сообщения об ошибке в блоке try и catch в Powershell

Создание отдельных исключений

Что бы обработать отдельную ошибку сначала нужно найти ее имя. Это имя можно увидеть при получении свойств и методов у значения переменной $Error:

$Error[0].Exception | Get-Member

Поиск имени для исключения ошибки в Powershell

Так же сработает и в блоке Catch с $PSItem:

Наименование ошибок для исключений в Powershell

Для вывода только имени можно использовать свойство FullName:

$Error[0].Exception.GetType().FullName

Вывод типа ошибок и их названия в Powershell

Далее, это имя, мы вставляем в блок Catch:

try {
   'svchost111','svchost' | % {Get-Process -Name $PSItem -ErrorAction 'Stop'}
}
catch [Microsoft.PowerShell.Commands.ProcessCommandException]{
   Write-Host "Произошла ошибка" -ForegroundColor RED
   $PSItem.Exception
}

Указываем исключение ошибки в блоке Try Catch Powershell

Так же, как и было описано выше мы можем усложнять эти блоки как угодно указывая множество исключений в одном catch.

Выброс своих исключений

Иногда нужно создать свои собственные исключения. Например мы можем запретить добавлять через какой-то скрипт названия содержащие маленькие буквы или сотрудников без указания возраста и т.д. Способов создать такие ошибки — два и они тоже делятся на критические и обычные.

Выброс с throw

Throw — выбрасывает ошибку, которая останавливает работу скрипта. Этот тип ошибок относится к критическим. Например мы можем указать только текст для дополнительной информации:

$name = 'AD.1'

if ($name -match '.'){
   throw 'Запрещено использовать точки в названиях'
}

Выброс ошибки с throw в Powershell

Если нужно, то мы можем использовать исключения, которые уже были созданы в Powershell:

$name = 'AD.1'

if ($name -like '*.*'){
   throw [System.IO.FileNotFoundException]'Запрещено использовать точки в названиях'
}

Выброс ошибки с throw в Powershell

Использование Write-Error

Команда Write-Error работает так же, как и ключ ErrorAction. Мы можем просто отобразить какую-то ошибку и продолжить выполнение скрипта:

$names = @('CL1', 'AD.1', 'CL3')

foreach ($name in $names){
   if ($name -like '*.*'){
      Write-Error -Message 'Обычная ошибка'
   }
   else{
      $name
   }
}

Использование Write-Error для работы с исключениями в Powershell

При необходимости мы можем использовать параметр ErrorAction. Значения этого параметра были описаны выше. Мы можем указать значение ‘Stop’, что полностью остановит выполнение скрипта:

$names = @('CL1', 'AD.1', 'CL3')

foreach ($name in $names){
   if ($name -like '*.*'){
      Write-Error -Message 'Обычная ошибка' -ErrorAction 'Stop'
   }
   else{
      $name
   }
}

Использование Write-Error и Stop в Powershell

Отличие команды Write-Error с ключом ErrorAction от обычных команд в том, что мы можем указывать исключения в параметре Exception:

Write-Error -Message 'Обычная ошибка' -ErrorAction 'Stop'

Write-Error -Message 'Исключение' -Exception [System.IO.FileNotFoundException] -ErrorAction 'Stop'

Свойства Write-Errror в Powershell

В Exception мы так же можем указывать сообщение. При этом оно будет отображаться в переменной $Error:

Write-Error -Exception [System.IO.FileNotFoundException]'Моё сообщение'

Свойства Write-Errror в Powershell 

Теги:

#powershell

#ошибки

Понравилась статья? Поделить с друзьями:
  • Ошибка шифрования квз
  • Ошибка чтения игрового диска iso поврежден ppsspp
  • Ошибка чтения конфигурации восстановительная конфигурация повреждена или отсутствует
  • Ошибка шифрования данных при попытке подключения rdp
  • Ошибка чтения контейнера описателей настроек starline