Tuesday, December 21, 2010

Powershell log time-stamping

The function 'logtime'  below will work as a logging function in scripts


$FileTime=[DateTime]::Now.ToFileTime()

function logtime{
$date = [DateTime]::Now.Day
$hour = [DateTime]::Now.TimeOfDay.Hours
$minutes = [DateTime]::Now.TimeOfDay.Minutes
$seconds = [DateTime]::Now.TimeOfDay.Seconds
$ms = [DateTime]::Now.TimeOfDay.Milliseconds

[object]$logtime = New-Object PSObject -Property @{
date=$date
hour=$hour
minutes=$minutes
seconds=$seconds
ms=$ms
}
write $logtime | ft -HideTableHeaders -AutoSize -Property date,hour,minutes,seconds,ms | out-file -append -noclobber $PWD\$FileTime

}


[output]
PS C:\Users\rferrisx\Documents> gc 129374235* | more

  21    8      45      43 821
  21    8      51      12 604
  21    8      51      12 616
  21    8      51      12 656
  21    8      51      12 662




Wednesday, December 8, 2010

System.Net.NetworkInformation.Ping

Here are some Powershell ping notes from System.Net.NetworkInformation.Ping.  Powershell v 2.0 provides for the  gwmi  based Win32_PingStatus  in the 'Test-Connection' cmdlet . 'Test-connection'  provides a wealth of information.  However this post simply examines how to use:
  • System.Net.NetworkInformation.Ping
  • System.Net.NetworkInformation.PingOptions
Below is the common code needed for all three examples. This code sets up $ping and $pingoptions:

#Set up the ping options
$ping = new-object System.Net.NetworkInformation.Ping
$pingoptions = new-object System.Net.NetworkInformation.PingOptions
$pingoptions.ttl=255
$pingoptions.dontfragment=$false
# Here is the overload
#  From $ping.send.overloaddefinitions  use: System.Net.NetworkInformation.PingReply Send(string hostNameOrAddress, int timeout, byte[] buffer, System.Net.NetworkInformation.PingOptions options)

#now ping a subnet with one line of code
(1..254 | % -process  {$Ping.Send("192.168.0.$_", 10, 64, $PingOptions)})
# or (stop output) or redirect to a variable:
$a=(1..254 | % -process  {$Ping.Send("192.168.0.$_", 10, 64, $PingOptions)})

This gives us something interesting like this:


PS C:\ps1> $a | where {$_.Status -eq "Success"} | ft * -auto


 Status Address       RoundtripTime Options                                   Buffer
 ------ -------       ------------- -------                                   ------
Success 192.168.0.1               2 System.Net.NetworkInformation.PingOptions {64}
Success 192.168.0.6               1 System.Net.NetworkInformation.PingOptions {64}
Success 192.168.0.11              0 System.Net.NetworkInformation.PingOptions {64}
Success 192.168.0.13              0 System.Net.NetworkInformation.PingOptions {64}


If you functionalize/filterize the output :
function pingsn {1..254 | % -process  {$Ping.Send("192.168.0.$_", 10, 64, $PingOptions)}}
filter success {if ($_.status -eq "Success") {($_.Address.IPAddressToString)+" "+($_.roundtriptime)}}
you get a similar output:
pingsn | success

192.168.0.1 1
192.168.0.6 1
192.168.0.9 0
192.168.0.11 1

We can also ping and array of names (as below) and retrieve similar information if we pipe the output to a variable. Or we can do something more CSV like:

#ping a multiple names
$DNS_array="google.com", "googel.com", "googley.com"
($DNS_array | % -process  {$Ping.Send("$_", 10, 64, $PingOptions)})

Status        : Success
Address       : 72.14.213.99
RoundtripTime : 29
Options       : System.Net.NetworkInformation.PingOptions
Buffer        : {64, 0, 0, 0...}


Status        : Success
Address       : 74.125.224.17
RoundtripTime : 38
Options       : System.Net.NetworkInformation.PingOptions
Buffer        : {64}


Status        : Success
Address       : 74.117.221.11
RoundtripTime : 96
Options       : System.Net.NetworkInformation.PingOptions
Buffer        : {64}


($DNS_array | % -process  {$Ping.Send("$_", 10, 64, $PingOptions)}) | 
% {$_.Address.IPAddressToString +","+  $_.Status +","+ $_.RoundTripTime}


72.14.213.99,Success,25
74.125.224.17,Success,38
74.117.221.11,Success,98

Something more clever to ping multiple subnets is needed. The code below isn't very fast. The use of a filter might speed it up. However, you can make it faster by specifying exactly the hosts you want in $Host_array.

#ping multiple subnets
[array]$Host_array=1..20
$Subnet_array="192.168.0","192.168.1","192.168.2"
$count=$Subnet_array.count
$i=0
do
{
$global:out = $host_array | % -process {$Ping.Send($Subnet_array[$i]+"."+$_ , 1, 64, $PingOptions)}
$out | % {if ($_.Address) {$_.Address.IPAddressToString +","+  $_.Status +","+ $_.RoundTripTime}}
$i=$i+1
}
while ($i -lt $count)