0

I have a script that runs through servers and prints out if they can connect to specific ports or not. The problem seems to be that it keeps on looping through existing servers its already done...hence I see multiple servers results and the CSV file keeps on getting re-written as each iteration restarts the cycle again to add on the next server.

Any ideas on ensuring it just cycles through one server at a time and not repeating the same server each time? The end CSV is fine as it contains the total servers but its taking ages to get there.

Output is below - you can see how it keeps on re-doing exisitng servers and just adding on one server more each time it runs:

Destination    Port 3389 Port 445 Port 80
-----------    --------- -------- -------
10.104.122.21  Failure   Failure  Failure
10.104.122.50  Failure   Failure  Failure
10.104.125.237 Failure   Failure  Failure



Destination    Port 3389 Port 445 Port 80
-----------    --------- -------- -------
10.104.122.21  Failure   Failure  Failure
10.104.122.50  Failure   Failure  Failure
10.104.125.237 Failure   Failure  Failure
10.104.125.66  Failure   Failure  Failure



Destination    Port 3389 Port 445 Port 80
-----------    --------- -------- -------
10.104.122.21  Failure   Failure  Failure
10.104.122.50  Failure   Failure  Failure
10.104.125.237 Failure   Failure  Failure
10.104.125.66  Failure   Failure  Failure
10.104.125.95  Failure   Failure  Failure

The code is below:

Function Test-PortConnections {
    [CmdletBinding()]

    # Parameters used in this function
    Param
    (
        [Parameter(Position=0, Mandatory = $True, HelpMessage="Provide destination source", ValueFromPipeline = $true)]
        $Destination,

        [Parameter(Position=1, Mandatory = $False, HelpMessage="Provide port numbers", ValueFromPipeline = $true)]
        $Ports = "80"
    ) 

    $ErrorActionPreference = "SilentlyContinue"
    $Results = @()

    ForEach($D in $Destination){
        # Create a custom object
        $Object = New-Object PSCustomObject
        $Object | Add-Member -MemberType NoteProperty -Name "Destination" -Value $D

        Write-Verbose "Checking $D"
        ForEach ($P in $Ports){
                #write-host "Port is $p"
                $timeout=100
                $requestCallback = $state = $null
                $client = New-Object System.Net.Sockets.TcpClient
                $beginConnect = $client.BeginConnect($d,$p,$requestCallback,$state)
                Start-Sleep -milli $timeOut
                if ($client.Connected -eq "True") { $Result = "True" } else { $Result = "False" }
                    $client.Close()
                        If($Result -eq "False"){ $status = "Failure" } else { $status = "Success" }

            $Object | Add-Member Noteproperty "$("Port " + "$p")" -Value "$($status)"
        }

        $Results += $Object

If($Results){
    $date = $(get-date -f yyyy-MM-dd)
    $Results | Format-Table -AutoSize
    $Results | Export-Csv -NoTypeInformation -Delimiter "," -Path H:\MyDocuments\Scripts\server_check_$($date).csv
}
}
} 

Test-PortConnections -Destination (Get-Content -Path "H:\MyDocuments\Scripts\servers.txt") -Ports 3389,445,80

4
  • It does not, but you keep writing all the previous results to the screen on each interation with $Results | Format-Table -AutoSize Commented May 12, 2020 at 16:25
  • @MathiasR.Jessen it does - that line, when taken out correctly shows nothing on the screen but the CSV keeps on changing size. I can't show it here but the size keeps on changing from 1KB to 0KB then 2KB and then 0KB etc...which implies its definitely looping through multiple times on the same server again and again. Commented May 12, 2020 at 16:31
  • 1
    Yes, because you keep accummulating results and overwriting the same file with the new total set of results :) Commented May 12, 2020 at 16:36
  • @MathiasR.Jessen - Yes, your right - I think I have fixed this now by moving the end bracket for the "Foreach" above the $date and that seems to have fixed it. Thanks. Commented May 12, 2020 at 16:45

1 Answer 1

1

Every time the outer foreach() loop runs, at the end you:

  1. Add current object to existing results ($Results += $object)
  2. Format and write ALL existing results to the screen ($Results | Format-Table -AutoSize)
  3. Export ALL the existing results to file ($Results | Export-Csv ...)

Export-Csv will simply overwrite the previously written file, so there you won't see a difference in the final result.

To fix this, I'd suggest simply having your function output $object on its own as soon as you reach the end of the loop body, and then either move the Export-Csv step outside the loop:

ForEach ($D in $Destination) {
    # Create a custom object
    $Object = New-Object PSCustomObject
    $Object | Add-Member -MemberType NoteProperty -Name "Destination" -Value $D

    Write-Verbose "Checking $D"
    ForEach ($P in $Ports) {
        #write-host "Port is $p"
        $timeout = 100
        $requestCallback = $state = $null
        $client = New-Object System.Net.Sockets.TcpClient
        $beginConnect = $client.BeginConnect($d, $p, $requestCallback, $state)
        Start-Sleep -milli $timeOut
        if ($client.Connected -eq "True") { $Result = "True" } else { $Result = "False" }
        $client.Close()
        If ($Result -eq "False") { $status = "Failure" } else { $status = "Success" }

        $Object | Add-Member Noteproperty "$("Port " + "$p")" -Value "$($status)"
    }

    Write-Output $Object
    $Results += $object
}

If ($Results) {
    $date = $(Get-Date -f yyyy-MM-dd)
    $Results | Export-Csv -NoTypeInformation -Delimiter "," -Path H:\MyDocuments\Scripts\server_check_$($date).csv
}

...or use Export-Csv with -Append, at which point you don't need $Results at all:

$date = Get-Date -Format yyyy-MM-dd
$ExportFileName = 'H:\MyDocuments\Scripts\server_check_${date}.csv'

ForEach ($D in $Destination) {
    # Create a custom object
    $Object = New-Object PSCustomObject
    $Object | Add-Member -MemberType NoteProperty -Name "Destination" -Value $D

    Write-Verbose "Checking $D"
    ForEach ($P in $Ports) {
        #write-host "Port is $p"
        $timeout = 100
        $requestCallback = $state = $null
        $client = New-Object System.Net.Sockets.TcpClient
        $beginConnect = $client.BeginConnect($d, $p, $requestCallback, $state)
        Start-Sleep -milli $timeOut
        if ($client.Connected -eq "True") { $Result = "True" } else { $Result = "False" }
        $client.Close()
        If ($Result -eq "False") { $status = "Failure" } else { $status = "Success" }

        $Object | Add-Member Noteproperty "$("Port " + "$p")" -Value "$($status)"
    }

    Write-Output $object
    $object | Export-Csv -Append -NoTypeInformation -Delimiter "," -Path $ExportFileName
}
Sign up to request clarification or add additional context in comments.

1 Comment

Forgot all about -append! Thanks for that - it fixes the issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.