Help Understanding What's Happening

I am trying to use an arraylist instead of the += to add items to an array. Unfortunately in this script I’m not getting the data I’m expecting.

This iteration of the script is producing the data (IP addresses) but runs very slow (I know it’s building the array with each addition)

#Result File
$Results = '.\ClientSitesResults.txt'

#Remove previous results file
Remove-Item -Path $Results -Force -ErrorAction SilentlyContinue

#Path to the netlogon.log file
$NetLogon = ".\netlogon.log"

#Load the netlogon.log file data
$data = Get-Content -Path $NetLogon

#Create Array to hold the split up entries
$NoClientSite = @()

$NoClientSite = $data | ForEach-Object -Process {
    $LineData = $_.Split(" ")
    if ($LineData[4] -eq 'NO_CLIENT_SITE:') {
        $NoClientSite += $LineData[6]
    }
}

$NoClientSites = $NoClientSite | Sort-Object

Add-Content -Path $Results -Value $NoClientSites -Encoding UTF8

However, when I convert the script to use the ArrayList instead of the expected IP addresses in the data. I’m getting int32 numbers…


#Result File
$Results = '.\ClientSitesResults.txt'

#Remove previous results file
Remove-Item -Path $Results -Force -ErrorAction SilentlyContinue

#Path to the netlogon.log file
$NetLogon = ".\netlogon.log"

#Load the netlogon.log file data
$data = Get-Content -Path $NetLogon

#Create Array to hold the split up entries
$NoClientSite = [System.Collections.ArrayList]@()

$NoClientSite = $data | ForEach-Object -Process {
    $LineData = $_.Split(" ")
    if ($LineData[4] -eq 'NO_CLIENT_SITE:') {
        $NoClientSite.Add($LineData[6])
    }
}

$NoClientSites = $NoClientSite | Sort-Object

Add-Content -Path $Results -Value $NoClientSites -Encoding UTF8

Something is turning the IP addresses into int32 numbers. I end up with a count from 1 to 280,000.
I’m using the ArrayList in other code and this isn’t happening there.

What gives?

In the vast majority of the cases that’s totally unnecessary.

Here an example :

Instead of adding every single element in each iteration to the array - what’s actually creating a new array with the old and the newly added elements like this:

$ServiceList = Get-Service
$Result = @()

foreach ($Service in $ServiceList) {
    $SingleService = 
    [PSCustomObject]@{
        Name   = $Service.Name
        Status = $Service.Status
    }
    $Result += $SingleService
}
$Result

You simply collect the output of the loop in a variable like this:

$ServiceList = Get-Service
$Result = 
    foreach ($Service in $ServiceList) {
        [PSCustomObject]@{
            Name   = $Service.Name
            Status = $Service.Status
        }
    }
$Result

… cleaner … easier to read and usually way faster … :wink:

I’m parsing the netlog file line by line and grabbing only the IP address listed and putting that into the array. It’s a simple array of IP addresses, nothing else.

Then I want to sort the array and make them unique. With nearly 300,000 lines of multiple duplicate entries of IP addresses the += takes forever to build the array (over an hour).

The ArrayList takes a couple of minutes but the data morphs into an integer instead of remaining the IP address.

I’m trying to understand what is happening to the data. Not find a different way of iterating through a set of data.

This still feels way too long. :wink:

Can you share a few sanitized example lines of your log file? (formatted as code please)

Here’s six lines of the log file.

09/06 23:59:34 [1112] DOMAIN: NO_CLIENT_SITE: (null) 192.168.XX.XX
09/06 23:59:59 [1112] DOMAIN: NO_CLIENT_SITE: (null) 192.168.XX.XX
09/07 00:55:48 [1112] DOMAIN: NO_CLIENT_SITE: (null) 192.168.XX.XX
09/07 00:58:07 [1112] DOMAIN: NO_CLIENT_SITE: XXXX21DD2 10.25.XX.XXX
09/07 00:58:24 [1112] DOMAIN: NO_CLIENT_SITE: XXXX21DD2 10.25.XX.XXX
09/07 00:58:42 [1112] DOMAIN: NO_CLIENT_SITE: XXXX21DD2 10.25.XX.XXX

The last column is the IP addresses I’m after. After storing them in an array the plan is to sort the array and make them unique. The vast majority of the entries are duplicates. The above shows just two IP addresses.

Arraylist are deprecated. It is recommended to use system.collections.generic.list instead. Arraylist output the index when you add an item, so if you insist on building a list vs capturing to a variable like Olaf showed, and insist on using the deprecated arraylist, you should void or null the output it creates.

$null = $deprecatedarraylist.Add($stuff)
1 Like

It should only taky seconds

Get-Content -Path .\netlogon.log |
ForEach-Object {
    if ($_ -match 'NO_CLIENT_SITE:') {
            ($_ -split ' ')[-1]        
    }
} | 
Sort-Object -Unique

Of course this code should run on the same machine where the log file is. Please do not access the log file via an UNC path. :wink:

1 Like

That’s really helpful. Thank you Olaf.