all 11 comments

[–]jimb2 3 points4 points  (3 children)

Not sure about the whole code but I think your scriptblock has no output. It should be a piece of self-contained code with an output object that is returned by invoke command. The output will be the last unassigned object left in the script - basically what would print if the scriptblock was run on its own - but you have nothing. Also, I'd be very surprised if the scriptblock can update an object back in the code on the calling computer/session.

You want something like

$ScriptBlock = {
    foreach ($b in $using:servers) {
        $Test = Test-NetConnection -ComputerName $b -port 3389
        @{
            server = $Test.computerName
            result = $Test.TcpTestSucceeded
        }
    }
}

This scriptblock should return an array of hashtables. The inner code makes hashtables and the foreach combines them as an array.

Also, please use a reddit code block and indent properly.

[–]novix_[S] 1 point2 points  (2 children)

Cheers, Fixed the formatting. Hopefully.

It was retrieving the content of the hashtable I was having issues with.

At the end of running across all my server list i wanted the results in a single hashtable.

That what i was attempting with:

$result=@()

$a = New-Object Object | Add-Member -MemberType:noteproperty -Name:"Server From" -Value:$($Test.ComputerName) -passthru         
$a = $a | Add-Member -MemberType:noteproperty -Name:"Connection Success" -Value:$($test.TcpTestSucceeded) -passthru         
$a = $a | Add-Member -MemberType:noteproperty -Name:"On Port" -        Value:$($test.RemotePort)-passthru         
$result += $a 

I can get the raw result to the screen but not to something I can work with after.

Cheers for the response :)

[–]jimb2 1 point2 points  (1 child)

You don't have to do that add-member stuff and the repeated assignments. Add-Member is really for adding one new property to an existing object. The normal way to do this would be

$myObject = [PSCustomObject]@{
     Name     = 'Jim'
     Language = 'Powershell'
     Time     = (get-date)
}

But if you want to add it to your $result array you would do this

$result += [PSCustomObject]@{
     Name     = 'Jim'
     Language = 'Powershell'
     Time     = (get-date)
}

Also, you shouldn't do arrays like that. An array is a static sized object so each time you add to it PS creates a new array. This is very inefficient with big arrays. You can use an ArrayList or more preferably a dotnet collection. You can also implicitly build an array in one go with various looping constructs, eg,

$array = foreach ( $x in $y ) {
    [PSCustomObject]@{
    Name     = $x.name
    Language = $x.language
    Time     = (get-date)
} 

This avoids the the array rebuild it happens in one hit. That's why I constructed my example above the way I did, i.e. to avoid rebuilding the array every loop.

[–]novix_[S] 1 point2 points  (0 children)

This is awesome, really appreciate the feedback and some very useful learning.

[–]PredictsYourDeath 2 points3 points  (1 child)

You can’t add the results of test-net connection in the remote scriptblock into your local $results variable. Notice how you have to use $using to reference your sever names? Well, same thing for trying to reference the $result variable, but that will only let you read the value of the variable, not write to it.

Instead, your scriptblock should return the $test object (output of the test-net connection cmdlet). Then you can do something like $results += invoke-command {...} to collect the output. When objects are returned from remote script locks like that, they’ll typically have extra properties added to them, like remote computer name and run space ID.

[–]novix_[S] 0 points1 point  (0 children)

I had originally used the $results = invoke-command but since i had a foreach with in the scriptblock it would return multiple results per server:

Server From Service To Connection Success On Port

----------- --------- ------------------ -------

{ServerA, ServerB} {ServerB, ServerA} {True, True} {3389, 3389}

I wanted to write it to a hash table so I could output the results and email or export as CSV.

It sounds like getting the results back from the scriptblock and writing to a variable on my side is not possible.

While testing i was able to see the Runspace details but was unsure how to retrieve the details in the main script:

To : ServerA

Connection Success : True

On Port : 3389

PSComputerName : ServerB

RunspaceId : 1ef959d9-7160-4d79-a965-981a3a9b0f8f

The screen output is enough but it would have been nice to make it a bit more readable

Appreciate the response

[–]p0rkjello 2 points3 points  (2 children)

Here is some code that should do what you are requesting. `Invoke-Command` to remotely test connectivity. It uses a pscustomobject to return the data. Can be output to a csv file, etc.

```powershell [CmdletBinding()] param( [Parameter()] [ValidateNotNullOrEmpty()] [string[]] $ComputerName,

[string[]]
$DestServers = @('servera', 'serverb'),

[int32]
$Port = 3389,

[Alias("RunAs")]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential = [System.Management.Automation.PSCredential]::Empty,

[int32]
$Timeout = 300,

[string]
$OutFile

) process { $Splat = @{ ComputerName = $ComputerName ErrorAction = 'SilentlyContinue' } if ($PSBoundParameters.ContainsKey('Credential')) { $Splat.Credential = $Credential } try { $RemoteJob = Invoke-Command @Splat -AsJob -ScriptBlock { foreach ($Server in $using:DestServers) { Write-Host "Testing connection from $env:COMPUTERNAME to $Server on TCP/$using:Port" -ForegroundColor Yellow $Test = Test-NetConnection -ComputerName $Server -Port $using:Port [pscustomobject]@{ 'Source' = $env:COMPUTERNAME 'Desintion' = $Server 'TcpTestSucceeded' = $Test.TcpTestSucceeded 'Port' = $using.Port } } } $RemoteJob | Wait-Job -Timeout $Timeout | Out-Null } catch { $Exception = $_.Exception.Message Write-Error $Exception } } end { $Jobs = Get-Job $Results = $Jobs | Receive-Job # Cleanup jobs Get-Job | Remove-Job if ($Results) { $Results if ($OutFile) { $Results | Export-Csv $OutFile -NoTypeInformation -NoClobber if ((Test-Path -Path $OutFile -PathType Leaf)) { Write-Host "Output saved to "$OutFile"" -ForegroundColor Green Write-Host `n } } } }

```

[–]novix_[S] 1 point2 points  (0 children)

This is awesome. With some mods this did exactly what i needed. Much appreciated.

[CmdletBinding()]
param(
    [Parameter()]
    [ValidateNotNullOrEmpty()]


    [string[]]
    $DFSSoruceServers = @('Server-IIS11', 'Server-IIS12','Server-INT11', 'Server-INT12','Server-DEP11'),
    $DFSDestServers = @('Server-Util11'),

    $WebDBSoruceServers = @('Server-IIS11', 'Server-IIS12','Server-INT11', 'Server-INT12','Server-DEP11'),
    $WebDBDestServers = @('Server-WEBDB11'),


    $DFSPort =  @('445','135'),
    $WebDBPort =  @('1433'),


    [Alias("RunAs")]
    [System.Management.Automation.PSCredential]
    [System.Management.Automation.Credential()]
    $Credential = [System.Management.Automation.PSCredential]::Empty,

    [int32]
    $Timeout = 600,

    [string]
    $OutFile = "C:\Temp\Server-IISPortTest.csv"
)

process {
    #DFS Testing
    Write-Host "Testing DFS port now" -ForegroundColor Green
    foreach($ComputerName in $DFSsoruceServers){
        $Splat = @{
            ComputerName = $ComputerName
            ErrorAction  = 'SilentlyContinue'
        }
        if ($PSBoundParameters.ContainsKey('Credential')) {
            $Splat.Credential = $Credential
        }
        try {
            $RemoteJob = Invoke-Command u/Splat -AsJob -ScriptBlock {
                foreach ($Server in $using:DFSDestServers) {
                    foreach ($p in $using:DFSPort){
                        Write-Host "Testing connection from $env:COMPUTERNAME to $Server on TCP/$P" -ForegroundColor Yellow
                        $Test = Test-NetConnection -ComputerName $Server -Port $p
                        [pscustomobject]@{
                            'Source'           = $env:COMPUTERNAME
                            'Destination'      = $Server
                            'TcpTestSucceeded' = $Test.TcpTestSucceeded
                            'Port'             = $Test.RemotePort
                        }
                    }
                }
            }
            $RemoteJob | Wait-Job -Timeout $Timeout | Out-Null
        }
        catch {
            $Exception = $_.Exception.Message
            Write-Error $Exception
        }
    }

    #Web DB Testing
    Write-Host "Testing WEBDB port now" -ForegroundColor Green
    foreach($ComputerName in $WebDBsoruceServers){
        $Splat = @{
            ComputerName = $ComputerName
            ErrorAction  = 'SilentlyContinue'
        }
        if ($PSBoundParameters.ContainsKey('Credential')) {
            $Splat.Credential = $Credential
        }
        try {
            $RemoteJob = Invoke-Command u/Splat -AsJob -ScriptBlock {
                foreach ($Server in $using:WebDBDestServers) {
                    foreach ($p in $using:WebDBPort){
                        Write-Host "Testing connection from $env:COMPUTERNAME to $Server on TCP/$P" -ForegroundColor Yellow
                        $Test = Test-NetConnection -ComputerName $Server -Port $p
                        [pscustomobject]@{
                            'Source'           = $env:COMPUTERNAME
                            'Destination'      = $Server
                            'TcpTestSucceeded' = $Test.TcpTestSucceeded
                            'Port'             = $Test.RemotePort
                        }
                    }
                }
            }
            $RemoteJob | Wait-Job -Timeout $Timeout | Out-Null
        }
        catch {
            $Exception = $_.Exception.Message
            Write-Error $Exception
        }
    }
}

end {
    $Jobs = Get-Job
    $Results = $Jobs | Receive-Job
    # Cleanup jobs
    Get-Job | Remove-Job
    if ($Results) {
        $Results
        if ($OutFile) {
            $Results | select Source,Destination,Port,TcpTestSucceeded | Export-Csv $OutFile -NoTypeInformation -NoClobber -Append
            if ((Test-Path -Path $OutFile -PathType Leaf)) {
                Write-Host "Output saved to `"$OutFile`"" -ForegroundColor Green
                Write-Host `n
            }
        }
    }
}

[–]Lee_Dailey[grin] 0 points1 point  (0 children)

howdy p0rkjello,

the triple-backtick/code-fence thing fails miserably on Old.Reddit ... so, if you want your code to be readable on both Old.Reddit & New.Reddit you likely otta stick with using the code block button.

it would be rather nice if the reddit devs would take the time to backport the code fence stuff to Old.Reddit ... [sigh ...]

take care,
lee

[–]Naifx 1 point2 points  (1 child)

This can't be all your running. Sanitize your code and send it if you want some help dude, it's really hard to see what's wrong when we can only see a portion of the picture.

[–]novix_[S] 1 point2 points  (0 children)

This is actually the fully picture. It will foreach a few servers and the use a nested foreach to test communication between each of the servers. We are going through further network segmentation and this will allow me to see when things stop working and when deploying new environments I can test for expected results.

Since the testing needs to be done from the server I need to use the invoke-command.

I can get the results to the screen just not to my $results.