1

I have a powershell script which runs some command on a local or remote computer. When the computer is remote then the command is called via Invoke-Command and a user is prompted for additional credentials.

A user can enter a script parameter which can be: hostname, IP, 127.0.0.1, alias from hosts file. I need to check if that parameter is for local or remote machine in order to call local command or Invoke-Command. I used to do it this way:

Function IsLocalhost {
    Param([string] $srvname)

    $script:AVLserverHost = $srvname.Split('\')[0]
    #Write-Host ("HOST: " + $script:AVLserverHost)

    if ((get-content env:computername) -eq $script:AVLserverHost) {
        return $true;
    } else {
        $AddressList = @(([net.dns]::GetHostEntry($script:AVLserverHost)).AddressList) 
        $script:HostIp = $AddressList.IpAddressToString

        $name = [System.Net.Dns]::gethostentry($script:HostIp)
        if ((get-content env:computername) -eq $name.HostName) {
            return $true
        }
    }
    return $false
}

But it only works on a domain DNS. Our computers are on a workgroup or a standalone computers that we can connect only by IP or alias from hosts file.

So how to check in powershell (or c# code) if given host is local or not, if the host is not in a domain DNS. I would like to have true/false if it is local or not and its real IP address if hostname or host alias was entered.

3 Answers 3

1

you could generate an array of the local IP's, add localhost to the array and then see if your parameter is in the array. here is a ps2.0 compatible version for ipv4.

$LocalArray = @()
$LocalArray += (gwmi Win32_NetworkAdapterConfiguration | ? {$_.IPAddress}) | select -expand ipaddress | select-string -notmatch ":"
$LocalArray += 'localhost'
$LocalArray += '127.0.0.1'
$LocalArray += hostname
$LocalArray -contains $IP
Sign up to request clarification or add additional context in comments.

3 Comments

In IPv4 any address from the range 127.0.0.0/8 (yes, all 16 million addresses) refers to localhost.
Thanks for this code but it doesn't cover all scenarios. On my local host I can have hosts file edited like this: 127.0.0.1 MyAlias1 , 10.148.0.1 MyAlias2. Both aliases refer to my local host (10.148.0.1 is my actual IP). The script should recognize MyAlias1 and MyAlias2 as localhost. Maybe the script could read hosts file and expand from it all aliases which referes to IPs that are already in $LocalArray
Actually $LocalArray -contains $IP doesn't work because first addresses returned from gwmi are [Microsoft.PowerShell.Commands.MatchInfo] and it cannot be compared with string $IP. I had to write foreach loop and convert all elements from $LocalArray into string.
1

You can try this:

function Is-LoopBackAddress([string] $Address)
{
    $addressIPs = [Net.Dns]::GetHostAddresses($Address).IPAddressToString

    $netInterfaces = [Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces()

    foreach ($netInterface in $netInterfaces)
    {
        $ipProperties = $netInterface.GetIPProperties()

        foreach ($ip in $ipProperties.UnicastAddresses)
        {
            if ($addressIPs -contains $ip.Address.IPAddressToString)
            {
                return $true
            }
        }
    }

    return $false
}

Is-LoopBackAddress 'localhost'

Comments

0

I combined @Noah's code with other example how to read hosts file and this is final code:

Function IsLocalhost {
    Param([string] $srvname)

    $script:AVLserverHost = $srvname.Split('\')[0]

    #get list of localhost addresses
    $localAddresses = @()
    $localAddresses += (gwmi Win32_NetworkAdapterConfiguration | ? {$_.IPAddress}) | select -expand ipaddress | select-string -notmatch ":"
    $localAddresses += 'localhost'
    $localAddresses += '127.0.0.1'
    $localAddresses += hostname

    $hosts = "$env:windir\System32\drivers\etc\hosts"

    [regex]$r="\S"   #define a regex to return first NON-whitespace character

    #strip out any lines beginning with # and blank lines
    $HostsData = Get-Content $hosts | where {
        (($r.Match($_)).value -ne "#") -and ($_ -notmatch "^\s+$") -and ($_.Length -gt 0)
    }

    $HostsData | foreach {
        $_ -match "(?<IP>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+(?<HOSTNAME>\S+)" | Out-Null
        $ip = $matches.ip
        $hostname = $matches.hostname

        if ($localAddresses -contains $ip) {
            $localAddresses += $hostname
        }
    }

    if ($localAddresses -contains $script:AVLserverHost) {
        return $true;
    } else {
        $script:HostIp = (Test-Connection $script:AVLserverHost | Select-Object IPV4Address)[0].IPV4Address.IPAddressToString
    }
    return $false
}

Comments

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.