none
Foreach -parallel in sequence. RRS feed

  • Question

  • Is there a way to run foreach –parallel in sequence? I tried this but it won’t run in sequence.

    workflow test

    {

    $servers = "servers.txt"

        foreach -parallel ($server in $servers)

        {

            sequence {

                        Test-Connection -ComputerName $server

                     }

        }

    }

    test 


    99upgrade

    Thursday, January 16, 2014 3:18 PM

Answers

  • OK.  Rather than using Test-Connection at all, then, I just went with using System.Net.Dns to do a lookup (specifically looking for IPv4, though you can tweak that if you want.)  If the name can't be resolved, or if it only resolves to non-IPv4 addresses, the IPAddress property of the resulting objects will be blank

    workflow test
    {
        $servers = "servers.txt"
        foreach -parallel ($server in get-content $servers) 
        {
            sequence
            {
                try
                {
                    $hostEntry = [System.Net.Dns]::GetHostEntry($server)
                }
                catch { }
    
                $ip = ''
    
                foreach ($address in $hostEntry.AddressList)
                {
                    if ($address.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetwork)
                    {
                        $ip = $address.IPAddressToString
                    }
                }
    
                [pscustomobject]@{
                    ComputerName = $server
                    IPAddress = $ip
                }
            }
        }
    }

    test | Format-Table ComputerName,IPAddress

    • Marked as answer by 99upgrade Thursday, January 16, 2014 5:40 PM
    Thursday, January 16, 2014 5:31 PM

All replies

  • I'm not sure I understand the question.  foreach -parallel is designed specifically to run things concurrently; ie, 'not' in sequence.  If you want things done one at a time, just use foreach without the -parallel switch.

    Thursday, January 16, 2014 3:21 PM
  • When I run this code, part of $server and part of Test-Connection -ComputerName $server executes randomly. For the output to make sense, I have to remove the –parallel switch and re-run.

     

    What I was hoping to see in the output was the servername and its IP below it, without compromising on the total time taken to complete the script.

     

    workflow test

    {

    $servers = "servers.txt"

        foreach -parallel ($server in get-content $servers)

        {

            sequence {

                        $server

                        Test-Connection -ComputerName $server

                     }

        }

    }

    test 


    99upgrade

    Thursday, January 16, 2014 4:22 PM
  • I see.  The two commands should be executing in order (with $server always coming before Test-Connection -ComputerName $server); however, you'll have many such commands all running at once, and the order that the output makes it to your screen will be unpredicable.

    A better approach would be to create a single object that is output from inside the body of the foreach -parallel loop, keeping the information all together while still executing in parallel.

    Thursday, January 16, 2014 4:49 PM
  • Could you share a simple repro?

    99upgrade

    Thursday, January 16, 2014 5:18 PM
  • Sure.  What information are you trying to get out of the Test-Connection command?  Just the IP address of the remote machine, or are you interested in whether it responded to pings, the response time, etc?
    Thursday, January 16, 2014 5:22 PM
  • Just the IP and it doesn't matter if they don't respond. You could also have the test-connection count to 1.

    99upgrade

    Thursday, January 16, 2014 5:28 PM
  • OK.  Rather than using Test-Connection at all, then, I just went with using System.Net.Dns to do a lookup (specifically looking for IPv4, though you can tweak that if you want.)  If the name can't be resolved, or if it only resolves to non-IPv4 addresses, the IPAddress property of the resulting objects will be blank

    workflow test
    {
        $servers = "servers.txt"
        foreach -parallel ($server in get-content $servers) 
        {
            sequence
            {
                try
                {
                    $hostEntry = [System.Net.Dns]::GetHostEntry($server)
                }
                catch { }
    
                $ip = ''
    
                foreach ($address in $hostEntry.AddressList)
                {
                    if ($address.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetwork)
                    {
                        $ip = $address.IPAddressToString
                    }
                }
    
                [pscustomobject]@{
                    ComputerName = $server
                    IPAddress = $ip
                }
            }
        }
    }

    test | Format-Table ComputerName,IPAddress

    • Marked as answer by 99upgrade Thursday, January 16, 2014 5:40 PM
    Thursday, January 16, 2014 5:31 PM
  • Thanks for helping out. Much appreciated!

    99upgrade

    Thursday, January 16, 2014 5:44 PM