2

I am query the Security EventLog on our PDC to watch for trends that might indicate compromised hosts or usernames. I have got the code to gather the info and clean it up...

$TargetEvents ends up like this: (I can't figure out how to format a normal looking table in my post)

Host  User
----  ----
host1 user1
host2 user2
host1 user3
host1 user4
host2 user4

$Events= Get-WinEvent -ComputerName MYPDC -FilterHashtable @{Logname='Security';id=4740} -MaxEvents 10
$TargetEvents=@()
foreach ($Event in $Events)
{

    $obj=[PSCustomObject]@{
        Host=$Event.Properties[1].value.ToString()
        User=$Event.Properties[0].value.ToString()
    }
    $TargetEvents+=$obj
}

I'd like to be able create a summary but I'm just genuinely stuck. I don't program professionally, just tools to help my work.

This is what I'm TRYING to create:

Host  Frequency
----  ---------
host1 3
host2 2

User  Frequency
----  ---------
user1 1
user2 1
user3 1
user4 2
dragonspeed
  • 255
  • 2
  • 13

2 Answers2

3

You can directly emit the [PSCustomObject] to a variable gathering the whole foreach output:

$Events= Get-WinEvent -ComputerName MYPDC -FilterHashtable @{Logname='Security';id=4740} -MaxEvents 10

$TargetEvents= foreach ($Event in $Events){
    [PSCustomObject]@{
        Host=$Event.Properties[1].value.ToString()
        User=$Event.Properties[0].value.ToString()
    }
}

To get your data you can use Group-Object here with -NoElement as only count (Frequency) and Host/ User are relevant

> $TargetEvents | Group-Object Host -NoElement

Count Name
----- ----
    3 host1
    2 host2

To get your exact desired output use a Select-Object to rename Count to Frequency with a calculated property.

$TargetEvents | Group-Object Host -NoElement | Select-Object @{n='Host';e={$_.Name}},@{n='Frequency';e={$_.Count}}

Host  Frequency
----  ---------
host1         3
host2         2

$TargetEvents | Group-Object User -NoElement | Select-Object @{n='User';e={$_.Name}},@{n='Frequency';e={$_.Count}}

User  Frequency
----  ---------
user1         1
user2         1
user3         1
user4         2
  • Thank you. This worked with what I had with minimal change. I had tried group but didn't know what the NoElement did, so it complained about not having an iCompare method etc... – dragonspeed May 03 '19 at 21:50
1

The Group-Object cmdlet is your friend here:

# rebuilding your example data

$items = @("host1 user1",
"host2 user2",
"host1 user3",
"host1 user4",
"host2 user4")

$arraylist = New-Object System.Collections.ArrayList

#loop over the objects, split at the space and assign variable values
foreach($item in $items) {
    $thehost = $item.split(' ')[0]
    $theuser = $item.split(' ')[1]

# including | Out-Null just keeps the Add() method from outputting the number of the item
# it does not nullify your data
    $arraylist.Add([PSCustomObject]@{Host=$thehost;User=$theuser}) | Out-null
}

# group by host property

$hostFrequency = $arraylist | Group-Object -Property Host

# group by user property

$userFrequency = $arraylist | Group-Object -Property User

# results arrays

$hostResults = New-Object System.Collections.ArrayList
$userResults = New-Object System.Collections.ArrayList

# group the count of hosts along with corresponding name
foreach($item in $hostFrequency)
{
    $hostResults.Add([PSCustomObject]@{Host = $item.Name; Frequency = $item.Count}) | Out-Null
}

# group the count of users along with corresponding name
foreach($item in $userFrequency)
{
    $userResults.Add([PSCustomObject]@{User = $item.Name; Frequency = $item.Count}) | Out-Null
}

# output all the things
$hostResults | Format-Table
$userResults | Format-Table

Output:

Host  Frequency
----  ---------
host1         3
host2         2



User  Frequency
----  ---------
user1         1
user2         1
user3         1
user4         2
trebleCode
  • 2,134
  • 19
  • 34