Foreach loop to foreach-object issues

Hi!

I have little script to ping and “nslookup” devices in out intranet.
To explain the code and why I do this is because we have trouble with our vpn and the given ip addresses. It’s a mess if I’m honest.

This is what the output looks like with the first code

device source ip source nslookup to device destination ip destination
device 1 99.99.1.1 ==> device 99 99.99.10.11
device 2 99.99.1.12 ==> device 78 99.99.24.33

Here’s the loop which works like it should be.

$vpnComputer = foreach ($computer in $csv) {
    #Write-Host $computer
    $deviceSource = [System.Net.Dns]::Resolve($computer.HostName) 
    $ipSource = $deviceSource.AddressList.IPAddressToString
    $deviceDest = [System.Net.Dns]::Resolve($ipSource)
    $ipDest = $deviceDest.AddressList.IPAddressToString
    
    if ($ipSource -like "99.99.*") {
        [PSCustomObject]@{
            Computer  = $deviceSource.HostName 
            IPAdresse = $ipSource
            $bla      = "==>"
            Ziel      = $deviceDest.HostName
            ZielIP    = $ipDest
            Abgleich  = if ($ipSource -eq $ipDest) { "Gleich" } else { "Unterschiedlich" }
        }
    }
}
$vpnComputer | Format-Table -AutoSize

Now I have to say that I need to ping nealry 9000 devices. I tried it with 1800 devices and it took 30 minutes.
So I wanted to parallelize the loop to ping 20 devices at once (for example).

Here’s the code:

$vpnComputer = $csv | ForEach-Object -Parallel -ThrottleLimit 20 {
    
    $deviceSource = [System.Net.Dns]::Resolve($_.HostName)
    $ipSource = $deviceSource.AddressList.IPAddressToString
    $deviceDest = [System.Net.Dns]::Resolve($ipSource)
    $ipDest = $deviceDest.AddressList.IPAddressToString

    if ($ipSource -like "99.99.*") {
        [PSCustomObject]@{
            Computer  = $deviceSource.HostName 
            IPAdresse = $ipSource
            $bla      = "==>"
            Ziel      = $deviceDest.Name 
            ZielIP    = $ipDest
            Abgleich  = if ($ipSource -eq $ipDest) { "Gleich" } else { "Unterschiedlich" }
        }
    }
}
$vpnComputer | Format-Table -AutoSize

With the foreach-object loop the handling of the variables is very different and “wrong” (because I don’t know how to use them properly).
And $vpnComputer is empty.

So my question is how to handle the variables right with the foreach-object?

It would be nice if someone can help me or point me to the right direction.

Kind regards

Alex

Hey Alex,

so to begin with, this code doesn’t run… likely cuz of the $bla so I’d suggest confirming that to start with:

Next, pretty sure you need to change the order of where your parallel is

ForEach-Object -ThrottleLimit 20 -Parallel {'Code Here'}

Parallel isn’t a switch, a script block needs to follow it: ForEach-Object (Microsoft.PowerShell.Core) - PowerShell | Microsoft Learn

Like I said, this loop works as expected.
The $bla variable is correct.

I will have a look at your link. Thanks.

Perhaps I am misunderstanding your intent but leading with ‘Like I said’ gives off a particular vibe. I’d humbly ask to be mindful of that in the future.

I’ve helped enough people to know that mistakes absolutely happen. I make them all the time myself. That’s why I asked, to make sure that was intended to be $bla, which would indicate some of the code wasn’t provided potentially. If the code doesn’t define $bla for what you shared, it’s impossible for me to know what that value is. Running the code as you shared it, errors out because $bla is missing in both of the code shares. In a custom object like that, it’s not nearly as common to use a variable on the left side of a statement, though it is done.

In this case it likely doesn’t matter, it’s merely a property name, but I pointed it out because you need to provide all the details when asking for help, as it does matter depending on the issue a person is running into.

1 Like

No, sorry, it was not meant the way I wrote it.

The variable is only this:
$bla = [char]0x20 + [char]0x20 + [char]0x20

Sorry for the double post.
I have now got it up and running.

If anyone is interested I can show the code.

I had to add some error handling for devices that are not reachable. This had caused an error within the loop.

Now it is as it should be.

With the normal foreach loop it took about 30 minutes for 1800 devices, with foreach-object -parallel with 2000 devices it takes about 45 seconds.

And both outputs match.

Even if no one is interested now you should share it anyway for any future readers comming here looking for a solution for the same of a similar issue. :man_shrugging:t3:

Thanks in advance.

You’re claiming that the value of $bla is 3 spaces? Surprisingly enough, that is a valid “property” inside a PSCustomObject.

$property = [char]0x20 + [char]0x20 + [char]0x20

[PSCustomObject]@{
    $property = 'some value'
}

---       
some value

$property = '   '

[PSCustomObject]@{
    $property = 'some value'
}

---       
some value

I’m still trying to figure out why anyone would want an empty looking property.

1 Like

In my first post in the table you can see nslookup to. This should be empty because ==> don’t need a header. That was the only reason.

1 Like

That’s great to hear! I presume then switching the order was at least, part of the issue? I think when I ran the code and switched the order it was successful though it may have thrown an error about something else I was missing, but it was likely something else you did have on your end.

If so, let me know and I will mark my answer as the solution (or you can as well).

I learned something today, thank you!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.