PDA

Показать полную графическую версию : [решено] Проблема с двойным Foreach


ivan.vas
15-09-2021, 15:57
Всем привет!
Помогите понять логику Foreach... Не могу понять почему скрипт который выглядит вот так:

$Time = (Get-Date) - (New-TimeSpan -Hours 24)
$events = @()
$events += Get-WinEvent -FilterHashtable @{Logname = "Security" ; ID = 4800,4801; StartTime = $Time}
$events += Get-WinEvent -FilterHashtable @{Logname = "System" ; ID = 7001,7002; StartTime = $Time}
$Date = Get-Date -format yyyy-MM-dd
$ArrayList = New-Object System.Collections.ArrayList
Foreach ($Event in $Events)
{
[xml]$Xml = $Event.ToXml()
$Row = "" | Select Username,TimeCreated,Operation
$Row.Username = $EventProperties[1].value
$Row.TimeCreated = $Event.TimeCreated.ToString()
$Row.Operation = $Event.ID
[void]$ArrayList.Add($Row)
}
$ArrayList | Sort TimeCreated


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


$Time = (Get-Date) - (New-TimeSpan -Hours 24)
$Servers = Get-Content "C:\temp\Comp.txt"
Foreach ($Server in $Servers)
{
if(Test-Connection $Server -Count 2 -Quiet ) {
$events = @()
$events += Get-WinEvent -ComputerName $Server -FilterHashtable @{Logname = "Security" ; ID = 4800,4801; StartTime = $Time}
$events += Get-WinEvent -ComputerName $Server -FilterHashtable @{Logname = "System" ; ID = 7001,7002; StartTime = $Time}
$Date = Get-Date -format yyyy-MM-dd
$ArrayList = New-Object System.Collections.ArrayList

Foreach ($Event in $Events)
{
[xml]$Xml = $Event.ToXml()
$Row = "" | Select Username,TimeCreated,Operation
$Row.Username = $EventProperties[1].value
$Row.TimeCreated = $Event.TimeCreated.ToString()
$Row.Operation = $Event.ID
[void]$ArrayList.Add($Row)
}
}
else {}
}
$ArrayList | Sort TimeCreated


Хочу к варианту который исправно работает (1 листинг) добавить возможность выборки имен компьютеров из файла txt.

Iska
15-09-2021, 17:29
ivan.vas, Вы на каждом проходе внешнего цикла пересоздаёте содержимое переменной $ArrayList:
Foreach ($Server in $Servers) {
if(Test-Connection $Server -Count 2 -Quiet ) {

$ArrayList = New-Object System.Collections.ArrayList

Foreach ($Event in $Events) {

[void]$ArrayList.Add($Row)
}

}
}
$ArrayList | Sort TimeCreated

ivan.vas
15-09-2021, 17:59
$ArrayList » честно говоря не понял. А где тогда правильно создать $ArrayList?

Iska
15-09-2021, 18:04
ivan.vas, перед первым циклом.

ivan.vas
16-09-2021, 09:17
перед первым циклом. »
Спасибо, помогло. Теперь скрипт выглядит вот так:

$Time = (Get-Date) - (New-TimeSpan -Hours 24)
$Date = Get-Date -format yyyy-MM-dd
$Servers = Get-Content "C:\temp\Comp.txt"
$ArrayList = New-Object System.Collections.ArrayList
Foreach ($Server in $Servers)
{
if(Test-Connection $Server -Count 2 -Quiet ) {
$events = @()
$events += Get-WinEvent -ComputerName $Server -FilterHashtable @{Logname = "Security" ; ID = 4800,4801; StartTime = $Time}
$events += Get-WinEvent -ComputerName $Server -FilterHashtable @{Logname = "System" ; ID = 7001,7002; StartTime = $Time}
Foreach ($Event in $Events)
{
$Row = "" | Select PC,Username,TimeCreated,Operation
$Row.PC = $Server
$Row.Username = $EventProperties[1].value
$Row.TimeCreated = $Event.TimeCreated.ToString()
$Row.Operation = $Event.ID
[void]$ArrayList.Add($Row)
}
}
else {}
}
$ArrayList | Sort TimeCreated


Единственное, что смущает, графы TimeCreated и Operation он выводит верно. Я даже добавил вывод имени компьютера вначале, но вот вывод имени пользователя дублирует одно и тоже. Не можете подсказать почему так?

DJ Mogarych
16-09-2021, 10:12
Гораздо быстрее будет работать, если воспользоваться Invoke-Command, типа


$Servers = Get-Content "C:\temp\Comp.txt"

Invoke-Command -ComputerName $Servers -ScriptBlock {
$time = (get-date).AddDays(-1)
Get-WinEvent -FilterHashtable @{Logname = "System" ; ID = 7001,7002; StartTime = $Time} |select PSComputername,@{n="Username";e={$_.properties[1].value}},Timecreated,id
}

ivan.vas
16-09-2021, 10:26
DJ Mogarych, но тогда нужно будет активировать у всех кто в списке Comp.txt - PSRemoting?

DJ Mogarych
16-09-2021, 10:52
Да, но у серверов это уже должно быть включено по умолчанию.

ivan.vas
16-09-2021, 12:49
DJ Mogarych, сервера разные бывают, иногда это даже 7 :)

Iska
16-09-2021, 17:04
но вот вывод имени пользователя дублирует одно и тоже. Не можете подсказать почему так? »
А откуда у Вас берётся $EventProperties[1]? Я вижу, что из воздуха. Может быть, $Event.Properties[1].value?

ivan.vas
16-09-2021, 17:21
А откуда у Вас берётся $EventProperties[1]? »
Из события "дергается".

Iska
16-09-2021, 21:44
ivan.vas, так «не дёргается». Именно «$EventProperties» — вообще ниоткуда.

DJ Mogarych
17-09-2021, 09:06
Да просто точка пропущена.

Iska
17-09-2021, 09:27
Да просто точка пропущена. »
Я про это автору и написал выше:
Может быть, $Event.Properties[1].value? »
Отсутствие требования явного описания переменых — зло.

ivan.vas
17-09-2021, 16:41
DJ Mogarych, Iska, вы правы, скрипт работал. Но потом вспомнив, почти тоже самое
Отсутствие требования явного описания переменых — зло. »
решил написать с заглавной буквы, это и была ошибка.
Правильно вот так выглядит:

[xml]$Xml = $Event.ToXml()
$Row = "" | Select Username,TimeCreated,Operation
$Row.Username = $eventProperties[1].value

Помогла вот эта картинка:
https://adamtheautomator.com/wp-content/uploads/2021/04/Untitled-89.png

Iska
17-09-2021, 21:04
ivan.vas, да без разницы, с заглавной или со строчной, PowerShell не различает регистр символов в переменной. Вы скорее всего пропустили точку, т.е. переменная зовётся не «$EventProperties», а «$Event», а «Properties» — её свойство/метод.

DJ Mogarych
18-09-2021, 08:35
Так и есть, и я в своём сообщении №6 выше в коде эту ошибку учёл.

ivan.vas
20-09-2021, 12:17
Iska, вы правы. Спасибо.




© OSzone.net 2001-2012