0

I have written/nabbed code that is designed to iterate through a list of hostnames, grab the IP's, and then log users off if they are not 'Active' on the machine. Iterating through the hostnames and putting a list of IP's into an array list works perfectly:

$HostNames = "google.com","facebook.com","test.com" #Create an array with the hostnames.

$IPList = [System.Collections.ArrayList]@() #Create an empty array list so we can add/remove objects. 

for ($i=0;$i -lt $HostNames.Length; $i++){ #Loop through the hostnames.
    [System.Net.Dns]::GetHostAddresses($HostNames[$i]) | foreach {$IPList.Add($_.IPAddressToString) } #Get all the IPs for the host and add them to the array.
}

When I call:

echo $IPList

I get the expected result:

216.58.198.78
31.13.73.35
69.172.200.235

The piece of code I stole from https://stackoverflow.com/a/35848515/3718225 also works perfectly when including the hostname or IP directly, such as:

$sessions = qwinsta /server "localhost" | ?{ $_ -notmatch '^ SESSIONNAME' } | %{#Return information about the selected server | Using the previous command, do not return a row where anything  matches SESSIONNAME in caps
$item = "" | Select "Active", "SessionName", "Username", "Id", "State", "Type", "Device" #Select what information to return
#All the items below this line trim up the session info. 
$item.Active = $_.Substring(0,1) -match '>'
$item.SessionName = $_.Substring(1,18).Trim()
$item.Username = $_.Substring(19,20).Trim()
$item.Id = $_.Substring(39,9).Trim()
$item.State = $_.Substring(48,8).Trim()
$item.Type = $_.Substring(56,12).Trim()
$item.Device = $_.Substring(68).Trim()
$item
}

But when I do something like:

$HostNames = "google.com","facebook.com","test.com" #Create an array with the hostnames.

$IPList = [System.Collections.ArrayList]@() #Create an empty array list so we can add/remove objects. 

for ($i=0;$i -lt $HostNames.Length; $i++){ #Loop through the hostnames.
    [System.Net.Dns]::GetHostAddresses($HostNames[$i]) | foreach {$IPList.Add($_.IPAddressToString) } #Get all the IPs for the host and add them to the array.
}

for ($i=0;$i -lt $IPList.Length; $i++){ #For all of the IP's in the array. 

    $sessions = qwinsta /server $IPList[$i]| ?{ $_ -notmatch '^ SESSIONNAME' } | %{#Return information about the selected server | Using the previous command, do not return a row where anything  matches SESSIONNAME in caps
    $item = "" | Select "Active", "SessionName", "Username", "Id", "State", "Type", "Device" #Select what information to return
    #All the items below this line trim up the session info. 
    $item.Active = $_.Substring(0,1) -match '>'
    $item.SessionName = $_.Substring(1,18).Trim()
    $item.Username = $_.Substring(19,20).Trim()
    $item.Id = $_.Substring(39,9).Trim()
    $item.State = $_.Substring(48,8).Trim()
    $item.Type = $_.Substring(56,12).Trim()
    $item.Device = $_.Substring(68).Trim()
    $item
    }

    foreach ($session in $sessions){ #For all the sessions
        if (($session.Username -ne "" -or $session.Username.Length -gt 1) -and ($session.State -eq 'Active')){ #So long as the session name is longer then 1 and not blank AND the session is not 'active'
            #logoff /server $IPList $session.Id
            Write-Host $IPList[$i] $session.Username $session.State #Disconnect the user. 
   }
  }
}   

I get an error:

Could not compare "0" to "13 11 14". Error: "Cannot convert the "System.Object[]" value of type "System.Object[]" to
type "System.Int32"."
At line:1 char:11
+ for ($i=0;$i -lt $IPList.Length; $i++){ #For all of the IP's in the a ...
+           ~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : ComparisonFailure

I have figured that I need to find a way to convert the ArrayList from a System.Object to a string. However, something like:

$IPList | out-string

Doesn't seem to work/be the solution. Why? What is the best way to convert this? I am not sure I understand why the $ArrayList stores strings as objects, and not strings.

HDCerberus
  • 2,113
  • 4
  • 20
  • 36

1 Answers1

2

Your loop is iterating the wrong number of items, to get the items count for the ArrayList or any other Array, use the Count Method, see ArrayList.Count

$IPList.Length will show the total character length of each item in the array while $IPList.Count will give you the total items in the Array.

So your Could not compare "0" to "13 11 14". error is:

google.com -> IP -> 216.58.206.78 Length -> 13
facebook.com -> IP -> 31.13.73.35 Length -> 11
test.com -> IP -> 69.172.200.235 Length -> 14

Replace the length in Count in this line:

for ($i=0;$i -lt $IPList.Length; $i++)

To this:

for ($i=0;$i -lt $IPList.Count; $i++)
Avshalom
  • 8,657
  • 1
  • 25
  • 43