4

let me start by saying I'm not good at all in writing scripts or troubleshooting them, thus me being here :)

I'm trying to find all the computers in a windows domain network that are using static IP addresses, I have made a small research online and found out this PowerShell script that goes as follow:

param ( 
    [string]$LDAPFilter = '(name=*)', 
    [switch]$Verbose 
) 
Get-ADComputer -LDAPFilter $LDAPFilter | 
% ` 
{  
    $name = $_.DNSHostName; 
    if ($Verbose.IsPresent) 
      { Write-Host -ForegroundColor Yellow "Connecting to $name..." }  
    $ints = Get-WmiObject -ErrorAction SilentlyContinue -ComputerName $name ` 
      -Query "select IPAddress, DefaultIPGateway from Win32_NetworkAdapterConfiguration where IPEnabled=TRUE and DHCPEnabled=FALSE"; 
    if ($ints -ne $null) 
        { 
            foreach ($int in $ints) 
            { 
                foreach ($addr in $int.IPAddress) 
                { 
                    $ip = $null 
                    if ($addr -match "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}") 
                    { 
                        $ip = $addr 
                        $gw = $null 
                        foreach ($gw_addr in $int.DefaultIPGateway) 
                        { 
                            if ($gw_addr -match "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}") 
                            { 
                                $gw = $gw_addr 
                                break 
                            } 
                        } 
                        if ($ip -ne $null) 
                        { 
                            $info = New-Object PSObject -Property ` 
                            @{ 
                                Name = $name 
                                IP = $ip 
                                Gateway = $gw 
                            } 
                            $info 
                            if ($Verbose.IsPresent) 
                                { Write-Host -ForegroundColor Yellow $info } 
                        } 
                    } 
                } 
            } 
        } 
} | 
Select-Object Name, IP, Gateway

I tried to run this on my Active Directory server, problem is, the script gives an error while running as follow:

Missing expression after unary operator '-'.
At C:\Users\Administrator.MyDomain\Desktop\ComputersWithStaticIP.ps1:24 char:8
+       - <<<< Query "select IPAddress, DefaultIPGateway from Win32_NetworkAdapterConfiguration where IPEnabled=TRUE an
d DHCPEnabled=FALSE";
    + CategoryInfo          : ParserError: (-:String) [], ParseException
    + FullyQualifiedErrorId : MissingExpressionAfterOperator

I traced my way to removing the "-" from the script, and then got this error instead:

ForEach-Object : Cannot bind parameter 'Process'. Cannot convert the " " value
of type "System.String" to type "System.Management.Automation.ScriptBlock".
At C:\Users\Administrator.MyDomain\Desktop\ComputersWithStaticIP.ps1:18 char:2
+ % <<<<  `
    + CategoryInfo          : InvalidArgument: (:) [ForEach-Object], Parameter
   BindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerSh
   ell.Commands.ForEachObjectCommand

What am I doing wrong? or what should I add/remove from the script to make it run?

Thanks,

2 Answers 2

7

What am I doing wrong?

The backtick ` is the line continuation character, and the first error you get 'missing expression after unary operator' appears to be PowerShell not seeing the -Query line as part of the previous line.

Possibly you are missing the ` at the end of the previous line in your copy of the script, or have got it replaced with an apostrophe by some quirk of copy/paste/font/editor code mangling, or something.

or what should I add/remove from the script to make it run?

Remove most of it, it's convoluted and ugly and redundant for what you want.

Why is it querying for Win32_NetworkAdapterConfiguration things and calling them ints? That's so misleading.

Why is it taking the IPAddress, calling it addr, then calling it ip, then calling it IP?

Why is it taking the GatewayAddress, calling it gw_addr, then gw, then Gateway?

The test for -eq $null seems needless, if you try to use foreach on an empty sequence it will work as expected (skip over it).

Using regexes to pick up IPv4 addresses instead of IPv6 addresses - useful, but waffly. IPv6 addresses use : to delimit them, and IPv4 addresses use ., so if you care for only IPv4 addresses, just look for a . in the address.

Why copy the address out, build a list of results, then select everything out of the list, when you could just print the address as you find it?

Do you even care at all about the gateway address?

Why test if the IP address is empty when you are in a block that's processing the IP address at this point so it can't be null at this point?

Why is the whole thing a chain using get-computers % { code } | select results, when that's no help to you?

I've pruned it back a bit and renamed things and got to the following clearer, simpler structure:

  1. Setup.
  2. Get the computers
  3. For each computer, get the network interfaces with static addresses.
  4. For each interface, get the IP addresses.
  5. For each IP address, identify the IPv4 ones by looking for .
  6. Display the computer name and this IPv4 address.

    param ( 
    [string]$LDAPFilter = '(name=*)'
    )
    
    $wmiQuery = "select IPAddress, DefaultIPGateway from Win32_NetworkAdapterConfiguration where IPEnabled=TRUE and DHCPEnabled=FALSE"
    
    $computers = (Get-ADComputer -LDAPFilter $LDAPFilter)
    foreach ($computer in $computers) { 
    
        $networkAdapters = (Get-WmiObject -ErrorAction SilentlyContinue -ComputerName $computer.DNSHostName -Query $wmiQuery) 
        foreach ($networkAdapter in $networkAdapters) { 
            foreach ($ip in $networkAdapter.IPAddress) 
            { 
                if ($ip -match "\.") 
                { 
                    Write-Host $($computer.DNSHostName), $ip } 
                }
        } 
    }
    

I haven't tested this completely, but it works against one computer to show just the name and static IPs.

N.B. it won't show you any names of computers that it can't contact, but then nor would the original one.

2
  • It worked perfectly, I now see a list of all computers in my network that are using a static IP, many thanks dude :) Oct 8, 2013 at 13:48
  • +1 for excellent PowerShell code review. =) Oct 20, 2013 at 4:51
0

You need to be careful of how the web page cuts your code up. Here's my modified version which works by OU in case you don't want every single computer tested and has a little more information as it runs.

############################################################################ 
## 
##  Script, that returns list of computers with first statically configured 
##  IP Address and Default Gateway. 
##  Requires Active Directory Module 
## 
##  Version: 1.0 
##  Author: [email protected] 
##  Date: 07#23#2012 
## 
############################################################################ 

# %Debug Arguments%='"Value1" "-Verbose"'

param ( [string]$LDAPFilter = '(name=*)', [switch]$Verbose ) 

import-module ActiveDirectory

# $LDAPFilter = '(name=*)'
# $Verbose = $True

if ($Verbose.IsPresent) 
    {
    $VerboseModeString = "enabled."
    $VerboseModeVar = $True
    }
Else
    {
    $VerboseModeString = "not enabled."
    $VerboseModeVar = $False
    }

# $VerboseModeVar = $True

Write-Host "Verbose mode is $VerboseModeString" -ForegroundColor Magenta


# LDAP Paths:
$Singapore_OU =     "OU=Singapore,OU=APAC,OU=TopOU,DC=MyDomain,DC=com"
$BC_OU =        "OU=BC,OU=Australia,OU=APAC,OU=TopOU,DC=MyDomain,DC=com"
$MAL_OF_OU =        "OU=KL Office,OU=Malaysia,OU=APAC,OU=TopOU,DC=MyDomain,DC=com"
$HK_OU =    "OU=HK Warehouse,OU=Hong Kong,OU=APAC,OU=TopOU,DC=MyDomain,DC=com"

Get-ADComputer -SearchBase $HK_OU -LDAPFilter $LDAPFilter | % `
{  
    $name = $_.DNSHostName; 

    if ($VerboseModeVar) 
      { Write-Host -ForegroundColor Yellow "Connecting to $name..." }  
    $ints = Get-WmiObject -ErrorAction SilentlyContinue -ComputerName $name -Query "select IPAddress, DefaultIPGateway from Win32_NetworkAdapterConfiguration where IPEnabled=TRUE and DHCPEnabled=FALSE"; 
    if ($ints -ne $null) 
        { 
            foreach ($int in $ints) 
            { 
                foreach ($addr in $int.IPAddress) 
                { 
                    $ip = $null 
                    if ($addr -match "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}") 
                    { 
                        $ip = $addr 
                        $gw = $null 
                        foreach ($gw_addr in $int.DefaultIPGateway) 
                        { 
                            if ($gw_addr -match "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}") 
                            { 
                                $gw = $gw_addr 
                                break 
                            } 
                        } 
                        if ($ip -ne $null) 
                        { 
                            $info = New-Object PSObject -Property `
                            @{ 
                                Name = $name 
                                IP = $ip 
                                Gateway = $gw 
                            } 
                            $info 
                            if ($Verbose.IsPresent) 
                                { Write-Host -ForegroundColor Yellow $info } 
                        } 
                    } 
                } 
            } 
        }
    else
        {
        if ($Verbose.IsPresent) 
            {
            Write-Host "--> Could not contact the computer $Name" -ForegroundColor Red
            }
        }

} | 
Select-Object Name, IP, Gateway

I've used this in my project to rebuild AD domain controllers in order to find static IPs which needs DNS changes and it works 100%!

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .