2

Test-NetConnection returns TRUE when run manually but when in a looping script, only some of the ports returns TRUE.


I wrote a powershell script that loops through port numbers to do a Test-NetConnection:

$machine = '[targetmachinename]'
$this_machine = $env:COMPUTERNAME
$port_arr = @(8331, 8332, 8333, 8334, 8335, 8310, 8311)

foreach ($port in $port_arr) {
    Test-NetConnection $machine.domain.name.com -port $port -InformationLevel Quiet
}

When I run the script, it always returns TRUE on the same two port numbers and returns FALSE on the other ports.

When I manually run the code for each port, they each come back as TRUE for all ports.

I have tried messing around with the port numbers by removing, adding, and moving them around but it always gives the same results with only the same two port numbers returning TRUE.

I suspected maybe the variable, array, foreach loop or something might be bad, but if that was the case, why would it work for the same two ports and not for the others even when I change up the array?
I was thinking about putting a delay or wait in between loops but have not tested it yet.

This script works fine when run locally from the target machine. Having this issue when running the script from another machine.


UPDATE: Looking at the powershell log:

Command start time: 20191111121539
**********************
PS>TerminatingError(New-Object): "Exception calling ".ctor" with "2" argument(s): "No connection could be made because the target machine actively refused it [IPADDRESS]:[PORT]""

I noticed that the IPADDRESS does not match up with the target machine name, but instead matches up with the source machine.


I replaced the $machine.domain.name.com to the actual ip address of the machine and that got the script working as expected.

Why does $machine.domain.name.com resolve to the source machine? Even if I concatenate that incorrectly, wouldn't that normally become an unresolved address and error? Shouldn't all port checks have failed at that point?

agent provocateur
  • 824
  • 3
  • 19
  • 39

2 Answers2

3

tl;dr

Replace argument

$machine.domain.name.com

with

"$machine.domain.name.com"

While unquoted command arguments in PowerShell are typically treated as expandable strings - i.e., as if they were implicitly enclosed in "...", this is not the case if your argument starts with a variable reference such as $machine.

In that case, PowerShell tries to evaluate the argument as an expression, and since [string] variable $machine has no .domain property (and subsequent nested properties), the entire argument effectively evaluates to $null[1] - resulting in inadvertent targeting of the local machine by Test-NetConnection.

The subtleties around how PowerShell parses unquoted command arguments:

Conversely, to learn about how expandable strings (string interpolation) - variable references and expressions embedded in "..." - work in PowerShell,


Additionally, BACON observes the following regarding the use of -InformationLevel Quiet with
Test-NetConnection:

I think passing -InformationLevel Quiet was actively impairing debugging in this case. Given $machine = 'foo', compare the output (particularly the ComputerName property) of:
Test-NetConnection $machine.domain.name.com -InformationLevel Quiet
vs.
Test-NetConnection $machine.domain.name.com
vs.
Test-NetConnection "$machine.domain.name.com".

In other words, [it's best to] ensure that the cmdlet (and its parameters) is behaving as expected before passing the parameter that says "I don't care about all that information. Just tell me if it passed or failed."


[1] $null is the effective result by default or if Set-StrictMode -Version 1 is in effect; with Set-StrictMode -Version 2 or higher, you would actually get an error.

mklement0
  • 382,024
  • 64
  • 607
  • 775
0

A common mistake I've seen people make (myself included) is in your variable name and usage in powershell. For example I forgot $ all the time. This is just looping through my machine as an example, but it tests all these ports correctly.

$port_arr = @(139,3389,5040)
$mac = @("myComputer")

foreach ($mc in $mac){
    foreach ($i in $port_arr) {
        Test-NetConnection  $mc -port $i

    }
}

Do you have an example of your powershell code? Also, have you stepped through to determine that it's working as expected?

JR87
  • 95
  • 8
  • @JR87 my looping script is pretty much identical to what you have posted. I have not yet stepped through it, but I have tried varying inputs with it, e.g. just doing one port at a time, etc. – agent provocateur Nov 11 '19 at 20:58
  • Just to be sure, because this can be impacted by things outside of your code. Are you running your "successful" tests from the same machine? If you have test1, test2, and target for example. If test1 doesn't have a firewall between it and target you're fine. If test2 DOES have a firewall between it and target, you could fail. Stupid, but possible in some cases. – JR87 Nov 11 '19 at 21:09
  • I have ran the command from the current machine that I am having issues running the script from (to the target machine) and that works fine. Just the script is being weird – agent provocateur Nov 11 '19 at 21:22
  • I have found the issue. the resolved ip address matches up with the source machine and not target machine. Any idea why the script might resolve to the source machine when I put $machine.domain.name.com in there? If I concatenated that variable incorrectly, shouldn't it ping an unresolved address and error? – agent provocateur Nov 11 '19 at 21:27
  • 2
    See mklement0's answer. It's because of how you structured your variable/string. – JR87 Nov 11 '19 at 22:16