Skip to main content
  1. Articles/

List IPs from remote servers

··1231 words·6 mins· loading
Rodrigo Silva
Author
Rodrigo Silva
20+ years in IT. That’s a lot of years.
Table of Contents

The easiest way to find a remote server’s IP is probably nslookup. But depending on how your environment is configured, not all IPs are automatically registered in the DNS. Servers with multiple network adapters that connect to different networks (an iSCSI SAN, for example) might only register the IPs used in the domain network.

Get-IPList
#

Get-IPList uses the good old ipconfig command to query all IPs configured on all adapters, and it filters the output so you have a clean list with only the IPs. It also has parameters you can use to manually enter remote servers or import them from a file or OU.

I will be explaining the script in details, but feel free to just go ahead and download the final script.

ipconfig
#

The reason I decided to go with ipconfig instead of PowerShell’s Get-NetIPAddress is that some servers might not have this comdlet available because of older PowerShell versions. I also prefer the way it sorts the IPs.

I started by removing all unnecessary lines from the output, keeping only the ones with IPv4 addresses. I used Select-String with the -pattern parameter to achieve that.

PS C:\Users\rsilva> ipconfig | Select-String -pattern "IPv4 Address"

   IPv4 Address. . . . . . . . . . . : 172.25.247.1
   IPv4 Address. . . . . . . . . . . : 192.168.86.59
   IPv4 Address. . . . . . . . . . . : 172.28.112.1

To remove the redundant text and keep the IPs only, I used the -split parameter in a foreach loop so it goes through each line of the string.

$split = "IPv4 Address. . . . . . . . . . . : "
$IPs = ipconfig | select-string -pattern "IPv4 Address"
            foreach ($IP in $IPs) {
                ($IP -split $split)[1]
            }

Invoke-Command
#

Now that we have a piece of code that can extract IPs from the ipconfig output, let’s add Invoke-Command to it so we can run the script against a remote server.

$split = "IPv4 Address. . . . . . . . . . . : "
$IPs = Invoke-Command -ScriptBlock {ipconfig | select-string -pattern "IPv4 Address"} -ComputerName server1
            foreach ($IP in $IPs) {
                ($IP -split $split)[1]
            }

You probably noticed the -ComputerName parameter we used to specify the server is native to Invoke-Command and we could technically add more servers (separated by comma) and run the script on all of them.

The problem with that approach, though, is that all IPs would be listed together and we wouldn’t be able to tell which IPs belong to each server. To avoid this inconvenience, we will be creating our own parameters.

ComputerName parameter
#

I will be calling the parameter -ComputerName because people are used to it from other PowerShell cmdlets, but you could name it “Server” or anything else you like.

To group the IPs by server, we only need to write the computer name before invoking the ipconfig script block. I used Write-Output for that and `n for a line break.

We will also need a new foreach loop for for the servers that are specified within the new parameter.

param(
    [Parameter()]
    [string[]] $ComputerName
)

$split = "IPv4 Address. . . . . . . . . . . : "

foreach ($Computer in $ComputerName) {

    Write-Output `n$Computer

    $IPs = (Invoke-Command -ScriptBlock {ipconfig} -ComputerName $Computer) | select-string -pattern "IPv4 Address"
    foreach ($IP in $IPs) {
        ($IP -split $split)[1]
    }
}

You can see below an example of the script running with the new parameter.

PS C:\Users\rsilva> .\Get-IPList.ps1 -ComputerName server1,server2,server3

server1
192.168.86.9
192.168.86.31
192.168.86.36

server2
192.168.86.8
192.168.86.11
192.168.86.49
192.168.86.50

server3
192.168.86.14
192.168.86.131

This alone should get the job done. But if something doesn’t go exactly as expected, PowerShell will throw several lines of red errors and suddenly things aren’t looking nice anymore.

From this point on, I’ll be adding some extras that include better handling of errors, new parameters to get the list of servers from an Active Directory OU or from a file, adding some colors to the output and an option for IPv6.

Other parameters
#

To add new parameters, we just need to declare them and specify what kind of data each one of them expect. Like -ComputerName, both -File and -OU require a string. -IPv6 doesn’t expect any data, so we set it up as a switch.

param(
    [Parameter()]
    [string[]] $ComputerName,
    [Parameter()]
    [string[]] $OU,
    [Parameter()]
    [string[]] $File,
    [Parameter()]
    [switch] $IPv6
)

The -ComputerName parameter saves its data (the server names) in the $ComputerName variable that is used in the main part of the code. To avoid rewriting the same code for -File and -OU, we will use the same variable to store the servers we get from them.

File
#

For this parameter we just need to get the content of the file. It’s as simple as Get-Content.

if ($File) {
    $ComputerName = Get-Content $File
}

OU
#

For this parameter we need to query Active Directory and restrict the -SearchBase to the specified OU. I also filtered the results to get only computers that are enabled, for obvious reasons.

if ($OU) {
    $ComputerName = Get-ADComputer -SearchBase "$OU" -filter {enabled -eq $True} | Sort-Object -Property Name | Select-Object -ExpandProperty Name
}

IPv6
#

Since this is a switch parameter, we will be using an if, else statement. If it exists, $IPversion and $split variables get IPv6 related values. If not, IPv4.

if ($IPv6) {
    $IPversion = "IPv6"
    $split = "Link-local IPv6 Address . . . . . : "
}
else {
    $IPversion = "IPv4"
    $split = "IPv4 Address. . . . . . . . . . . : "
}

Before we had the $IPversion variable, values for IPv4 were hardcoded, so we also have to make adjustments for the code to use the variable instead. You will see it in the code snippet when we talk about handling errors below.

Handling errors
#

To better handle errors that the script might throw (a server not reachable, for example), we will be using Try, Catch blocks.

If an error occurs within the Try block, the error is first saved to the $Error variable. PowerShell then searches for a Catch block to handle the error, and that’s where we can make the error message look better.

try {
    $IPs = (Invoke-Command -ScriptBlock {ipconfig} -ComputerName $Computer -ErrorAction Stop) | select-string -pattern $IPversion
    foreach ($IP in $IPs) {
        ($IP -split $split)[1]
    }
}

catch {
    outputColor -fgcolor "Yellow"
    Write-Output "Server is not reachable. Error details:"
    outputColor -fgcolor "DarkGray"
    Write-Output $_`n
    outputColor -reset
}

outputColor function
#

You probably noticed in the Catch block above a function called outputColor with some color parameters. Unlike Write-Host, Write-Output doesn’t have parameters to change host colors.

To deal with this limitation, I decided to create this additional function to “prettify” the output in the console.

It has parameters for foreground and background colors, -fgcolor and -bgcolor respectively. It also saves the current colors in variables, so we can bring it back to what it was with the -reset parameter.

$bgDefColor = $host.ui.RawUI.BackgroundColor
$fgDefColor = $host.ui.RawUI.ForegroundColor

function outputColor {

    Param ([string]$bgcolor, [string]$fgcolor, [switch]$reset)

    if ($bgcolor) {
        $host.ui.RawUI.BackgroundColor = $bgcolor
    }

    if ($fgcolor) {
        $host.ui.RawUI.ForegroundColor = $fgcolor
    }

    if ($reset) {
        $host.ui.RawUI.BackgroundColor = $bgDefColor
        $host.ui.RawUI.ForegroundColor = $fgDefColor
    }
}

Install
#

You can fork the final script on Github or install it from PowerShell Galery.

  Fork     Install