/\/\o\/\/ PowerShelled

This blog has moved to http://ThePowerShellGuy.com Greetings /\/\o\/\/
$AtomFeed = ("Atom.xml")
$PreviousItems = (" PowerShell and SMS 2003 "," Upgrading MSH, My first Windows PowerShell Commands "," Some more Windows PowerShell Links and info. "," Windows PowerShell (Monad / MSH) "," Simple port scanning using Monad "," Large AD queries in Monad "," Sharepoint provider for Monad "," access ADSI WinNT provider from Monad Part 2 "," MSH Community Workspace, TFSC provider and videos "," more Monad scripts, and a bit more CSV "," ")

Wednesday, April 26, 2006

 


PowerShell AD site Finder



In this post an example function/script (get-Site) that will find the AD site from a given IPAddress or Hostname.

In this script two nice new features in PowerShell are shown :

byRef Parameters and Switch Parameters.

also you could see I started using new aliases a couple of weeks ago.
I waited a long time using the common % and ? aliases as I keep forgetting them (see new on my blog) but now the fist one its still mine but the others are standard !
so these line are not necessary anymore :

# check needed aliases
if (!(get-command -ea SilentlyContinue new)) {set-alias new New-Object}
if (!(get-command -ea SilentlyContinue %)) {set-alias % ForEach-Object}
if (!(get-command -ea SilentlyContinue ?)) {set-alias ? Where-Object}
if (!(get-command -ea SilentlyContinue gwmi)) {set-alias gwmi get-WMIObject}


and you will see them a lot more ;-)

an other thing to note is that I did split up the function in 2 parts

the function Find-site and the function Get-site.
I do this becouse I like to paste code into the PowerShell Console.

b.t.w. this is also why I always put the { at the end of the line (oposed to on the next line) and why I never use tabs in the examples this is to keep it parsable from the interactive prompt , so that I can paste it. in a script this is not needed, but this keeps the samples easy to try.

if you want to build it in a script, this would be a more common form :

# get-Site.ps1
param ($Computer,[switch]$Verbose)

# Main function
Function Main {}

# helper functions

function FindSiteByIp {}

# Start Main Function

. Main


but to test by pasting them into the commandline when needed, I wil use 2 functions

The first function is the WorkHorse :

it will take a net.ipAddress Object as input, calculate possible Subnets of the IP number and try to find the subnet in AD till it does find one, then it does list the subnet and Site info from AD.

*Note* again for the example I did declare the AD stuff in one place, in a production script you would declare it only once and just set the filter in the loop.
but now with no AD handy its easy to remark the AD part and more readable I think for an example.

the first function does look like this :

# find the AD site from a given IP Number
# Helper Function for Get-Site Function / Script
# /\/\o\/\/ 2006 
# http:/mow001.blogspot.com

Function find-Site {
  param ([net.ipAddress]$ip)

  # Resolve possible NetworkNumbers

  for ($bit = 30 ; $bit -ge 1; $bit--){
    [int]$octet = [math]::Truncate(($bit - 1 ) / 8)
    $net = [byte[]]@()
    for($o=0;$o -le 3;$o++) {
      $ba = $ip.GetAddressBytes()
      if ($o -lt $Octet) {
        $Net += $ba[$o]
      }ELSEIF ($o -eq $octet) {
        $factor = 8 + $Octet * 8 - $bit
        $Divider = [math]::pow(2,$factor)
        $value = $divider * [math]::Truncate($ba[$o] /  $divider)
        $Net += $value
      }ELSE {
        $Net += 0
      }
    }
    $NetWork = [string]::join('.',$net) + "/$bit"

    # try to find Subnet in AD

    if ($verbose.IsPresent) {write-host -fore 'yellow' "Trying : $network"}
    $de = new directoryservices.directoryentry('LDAP://rootDSE')
    $Root = new directoryservices.directoryentry("LDAP://$($de.configurationNamingContext)")
    $ds = new directoryservices.directorySearcher($root)
    $ds.filter = "(CN=$NetWork)"
    $r = $ds.findone()
  
    # If subnet found, write info and exit script.

    if ($r) {
      write-host -fore 'yellow' "AD Site found for $IP :"
      $r.properties.name
      $r.properties.description
      $r.GetDirectoryEntry().siteObject
      break
    }
  }
}


You will see some math to calculate the different network ID's possible.

then it will connect to the RootDSE to get the configurationNamingContext, connects to that with a Directory Searcher to find the subnet.

note also the :

$r.GetDirectoryEntry().siteObject

to get from the searchresult to the directoryentry and then to the Site Object.

I will not go into that in this post but search for AD on my blog (top or botom of page) to find more info about PowerShell and AD and for Byte for more info about the Math .

this Math was from an Old VB.NET "script" I made, working from former byte examples, this would be a way also : (I made this to refresh my IP math, from other byte examples) ;-)

# List possible networks for IP number
# /\/\o\/\/ 2006  
# http://mow001.blogspot.com 
function Parse-IP {
 param ($sIp)
 $ip = 0
 if([net.IPAddress]::TryParse($sIP,[ref]$ip)){
   $Bytes = $ip.GetAddressBytes()
   for ($bits = 30;$bits -gt 0; $bits--) {
     Switch ([system.Math]::Truncate($bits / 8)){
       3 {
           $script:sum = 0 ; for ($i= (8 - ($bits - 24));$i -le 7;$i++){if ($bytes[3] -band [math]::pow(2,$i)) {$script:sum += ([math]::pow(2,$i))}}
           "$($bytes[0]).$($bytes[1]).$($bytes[2]).$script:sum/$bits"
         }
       2 {
           $script:sum = 0 ; for ($i= (8 - ($bits - 16));$i -le 7;$i++){if ($bytes[2] -band [math]::pow(2,$i)) {$script:sum += ([math]::pow(2,$i))}}
           "$($bytes[0]).$($bytes[1]).$script:sum.0/$bits"}
       1 {
           $script:sum = 0 ; for ($i= (8 - ($bits - 8));$i -le 7;$i++){if ($bytes[1] -band [math]::pow(2,$i)) {$script:sum += ([math]::pow(2,$i))}}
           "$($bytes[0]).$script:sum.0.0/$bits"
         }
       0 {
           $script:sum = 0 ; for ($i= (8 - ($bits));$i -le 7;$i++){if ($bytes[0] -band [math]::pow(2,$i)) {$script:sum += ([math]::pow(2,$i))}}
           "$script:sum.0.0.0/$bits"
         }

            }
   }
 }
}
# test Code

parse-ip 130.144.215.100 


this script also shows the usage of the [ref] variable in tryParse()
But on to the Second (not counting parse-IP sample), Script.

this will do 2 things, first it checks if the $computer parameter is an IP Address
by doing a tryParse() , (this method is much nicer to work with as the Parse function, as you canuse it in an IF statement as in the Example.
Before in Monad/MSH this was not yet possible as the [ref] type was not supported yet.) if its not an IP number it will assume it is a hostname and will try to ping it to get the IP adress. (if ICMP is disabled, but you are admin on the remote, you can also consider adding a WMI try also to get the IP address (for more WMI info search for WMI on my blog)

the Second thing you will see is the use of the [switch] parameter, as the boolean behavour is changed (see also release notes)

so the second script is a wrapper to make it more easy to use the find-ip function.

this script looks like this :

# find the AD site from a given IP Number
# Will Find an AD site from an IP Number or a Hostname
# /\/\o\/\/ 2006 
# http://mow001.blogspot.com

Function Get-site {
  param ($Computer,[switch]$Verbose)
  $ip = 0
  if ([net.ipaddress]::tryparse($computer,[ref]$ip)) {
    find-site $ip
  }ELSE{
    if ($verbose.IsPresent) {write-host -fore 'yellow' "$Computer is No IP Address, trying Ping"}
    $ping = new Net.NetworkInformation.Ping
    &{TRAP{$ip = $null;continue}
      if ($verbose.IsPresent) {write-host -fore 'yellow' "Pinging : $computer"}
      $ip = $ping.send("$Computer").address
      if ($ip) {
        write-host -fore 'yellow' "$computer resolved to $ip";find-site $ip
      }ELSE {
        write-host -fore 'yellow' "$computer Not found"
      }
    }
  }
}


and the 2 together can be used like this :

Get-site 10.10.215.249
Get-site mowPC44
Get-site mowPC44 -verbose

You see in the examples below Used the [switch] to togle verbose mode to output more info (shortened to -V), and in the scripts I use :

if ($verbose.IsPresent) {write-host -fore 'yellow' "text"}

constructions to output the extra info (only to console not to pipeline !).

Usage Examples :



# Get-Site using IP number

MowPS>Get-site 10.10.215.249

AD Site found for 10.10.215.249 :
10.10.208.0/20
MOW The Netherlands
CN=Mow-01,CN=Sites,CN=Configuration,DC=Mow,DC=com

# get site using HostName

MowPS>Get-site MowPC44

MowPC44 resolved to 10.10.215.249
AD Site found for 10.10.215.249 :
10.10.208.0/20
MOW The Netherlands
CN=Mow-01,CN=Sites,CN=Configuration,DC=Mow,DC=com

# Using Verbose Mode :

MowPS>Get-site mowPC44 -v

MowPC44 is No IP Address, trying Ping
Pinging : MowPC44
MowPC44 resolved to 10.10.215.249
Trying : 10.10.215.248/30
Trying : 10.10.215.248/29
Trying : 10.10.215.240/28
Trying : 10.10.215.224/27
Trying : 10.10.215.192/26
Trying : 10.10.215.128/25
Trying : 10.10.215.0/24
Trying : 10.10.214.0/23
Trying : 10.10.212.0/22
Trying : 10.10.208.0/21
Trying : 10.10.208.0/20
AD Site found for 10.10.215.249 :
10.10.208.0/20
MOW The Netherlands
CN=Mow-01,CN=Sites,CN=Configuration,DC=Mow,DC=com


You see that the Wrapper makes a a lot easier, by checking the IP number and the option to use a hostname using ping, I use the Ping version to locate SMS roaming clients, to check DPs.

Enjoy,

Greetings /\/\o\/\/
Tags :


Comments:
Anonymous Anonymous
Halo, nice design.
My site here [url=http://viagra-store.info/]viara[/url].
Here you can buy http://viagra-store.info#viagra online.
thanks.
 
Anonymous Anonymous
How do you do?, best.
My home page [url=http://www.jahk.org/forum/topic.asp?TOPIC_ID=113]viagra[/url].
Take http://www.jahk.org/forum/topic.asp?TOPIC_ID=113#viagra best.
thanks.
 
Post a Comment



<< Home

Archives

October 2005   November 2005   December 2005   January 2006   February 2006   March 2006   April 2006   May 2006   June 2006   July 2006   August 2006   September 2006   October 2006   November 2006   December 2006  

$Links = ("PowerShell RC1 Docs"," PowerShell RC1 X86"," PowerShell RC1 X64"," Monad GettingStarted guide"," Monad Progamming Guide"," Monad SDK"," Monad videos on Channel 9"," MSH Community Workspace"," scripts.readify.net "," MonadSource"," www.reskit.net"," PowerShell Blog"," Under The Stairs"," computerperformance powershell Home"," proudlyserving"," MSH on wikipedia"," MSHWiki Channel 9"," Keith Hill's Blog"," Precision Computing"," PowerShell for fun"," MSH Memo (Japanese)"," monadblog")

find-blog -about "PowerShell","Monad" | out-Technorati.
find-blog -contains "","" | out-Technorati.
Google
 
Web mow001.blogspot.com

This page is powered by Blogger. Isn't yours?