Monday, February 23, 2009

Teaching myself debugging...some random notes:

There are no locals or watch windows in the CTP2  v3 ISE. They are sorely needed.  However, there is a plethora of debugging facilities in Powershell. Today's post is about my morning exploration  of such facilities. I have a function List-TCPConnections that works fine with one argument but doesn't work with multiple pipeline values.  This param: [ValueFromPipeline] gives me a "load assembly" error message and I am not ready to debug that right now ;-) .  I have a cmd.exe test script to give myself connection states: for /l %i in (1000,100,10000) do wget  I run through TCP Connection States like this: '0..11 | %{List-TCPConnections $_}'

Under such test, the function below works as expected, pumping out connection states, IP addresses to console and (classic) EventLog:
function global:List-TCPEstablished {do {List-TCPConnections 5} while (1)}

This  (pipeline function) does not work :
function global:List-TCPAllStates {do {0..11 | %{List-TCPConnections $_}} while (1)}  

Originally, I tried some simple 'print debug' type strategies with "get-variable" (gv) and  "out-gridview". But the compound variables do not Invoke() (for me)  in "out-gridview" so these strategies weren't helping. 

   (gv -s 0)| out-gridview ## scope for everything
   (gv -s 1)| out-gridview ## one scope up

   ## Just what the script gives subtracted from everything
    compare-object (gv -s script) (gv -s 0) | out-gridview

Along the same lines, I thought I would be more tricky and pump out  variable arrays I wanted to watch  as needed: 


    $dbg = $local_out | %{gv ($_)}; $dbg | out-gridview

That still wasn't helpful for the above reasons. Below, the trace command dumps lots of information, but still doesn't help me with logic errors:

trace-command -name metadata,parameterbinding,cmdlet -option ExecutionFlow,data,errors {do {0..11 | %{List-TCPConnections $_};sleep -s 5} while (1)}-pshost

Using a script block at the start of my Begin{} function and calling it as needed  was most useful at this point.

## Debug Print Script Block
    write .

 ## Debug
    write $Locals_out.Invoke()

to be continued...

Wednesday, February 18, 2009

Three of the four last posts have resulted in a considerable speed up of my Powershell learning curve. In my February 6th post , I created a (not so) simple script to log all new Established TCP Connections.  'Compare-Object' was very useful in finding the diff between one netblock and the last. In my February 12th post, I worked through how to send those Established TCP Connections to the (classic) Event Viewer.  I then spent quite a bit of time trying to build a script that iterated all TCPStates past the current TCP Connection diff in an attempt to send all TCP State Connections to the Event Log.  I spent a lot of time failing to create such an iteration. (Update February 25): Eventually, I did create a function(s) which will log select TCP Connection States. It is posted here:
 There are a ton of issues for me to work out with Powershell involving .NET overloads, Functions Types, Iteration, Parameters....But the foreach-object can be used in a block to process an  array line by line. Very simple and straightforward:
       $global:c = compare-object -referenceobject $State_netblock -differenceobject $State_last_netblock
       if ($c -eq $null){}
       elseif($c.SideIndicator -eq "<=" )
          {$C |
                foreach-object -process{                                    
                $LocalAddress = $_.InputObject.LocalEndPoint.Address
                $RemoteAddress = $_.InputObject.RemoteEndPoint.Address           
                $LocalPort = $_.InputObject.LocalEndPoint.Port
                $RemotePort = $_.InputObject.RemoteEndPoint.Port
                $TCP_State = $TCPState[$State]
                $name = [System.Net.DNS]::Resolve("$RemoteAddress")
                $name_canon = $name.hostname
                write "$TimeNow $RemoteAddress $name_canon : $RemotePort $TCP_State"
                $EventLog.Source = "$name_canon" 
                $EventLog.WriteEntry("$LocalAddress $TCP_State connection to $RemoteAddress($name_canon) from Local Port: $LocalPort to Remote Port: $RemotePort",$infoevent,$RemotePort,$State) 


Update on event log queries for the event log generated by the above script:

$Source_8NetUnique = get-eventlog -log EstablishedTCPConnections  | ?{$_.Source -match "^8\."} | sort-object -property Source -unique
$SourceNetUnique = get-eventlog -log EstablishedTCPConnections  | ?{$_.Source -match "^*"} | sort-object -property Source -unique
$SourceNetUniqueGroupBy = get-eventlog -log EstablishedTCPConnections  | ?{$_.Source -match "^*"} | group-object -property Source | Sort-object -property count -descending
Function Get-NetName ($CountNetName) { get-eventlog -log EstablishedTCPConnections  | ?{$_.Source -match "^$CountNetName"} |  group-object -property Source | Sort-object -property count -descending}
foreach($i in (gc alpha.txt)){get-netname $i}
$Port80 = get-eventlog -log EstablishedTCPConnections  | ?{$_.EventID -match "^80"}|  sort-object -property TimeGenerated -descending
$EventIDNetUnique = get-eventlog -log EstablishedTCPConnections  | ?{$_.EventID -match "^*"} | sort-object -property EventID -unique
$EventIDNetUniqueGroupBy = get-eventlog -log EstablishedTCPConnections  | ?{$_.EventID -match "^*"} | group-object -property EventID | Sort-object -property count -descending
Function Get-PortType ($CountPortType) { get-eventlog -log EstablishedTCPConnections  | ?{$_.EventID -match "^$CountPortType"} |  group-object -property EventID | Sort-object -property count -descending}

$Source = get-eventlog -log EstablishedTCPConnections | group-object -property Source | sort-object -property Count -descending
$Port = get-eventlog -log EstablishedTCPConnections | group-object -property EventID  | sort-object -property Count -descending

$UniqSource = get-eventlog -log EstablishedTCPConnections |  sort-object -property Source -descending -unique 
$UniqPort = get-eventlog -log EstablishedTCPConnections |  sort-object -property EventID -descending -unique 

$UniqSource = get-eventlog -log EstablishedTCPConnections | group-object -property Source | sort-object -property Count -descending
$UniqSource | Select Count,Name | cvhtml > UniqSource.html

$a | %{[System.Net.DNS]::Resolve($_.Source)}
$a | %{whois ($_.Source)}           

Thursday, February 12, 2009

This function pushes off the stack every new Established TCP connection as so:

PS >List-EstablishedTCP : 80 : 80 : 80 : 80 : 80 : 80 : 80

It also send a message to the (classic) Event Log named "EstablishedTCPConnections" as shown here.  One PoSh blog was very helpful with this:

function Global:EstablishedTCP 
{ ## start function

    $a = [System.Net.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties()
    $b = $a.GetActiveTcpConnections() | where{$_.State -eq "Established" }
    if ($b -ne $null -and $last_b -ne $null) 
    $c = compare-object $b $last_b;
    if ($c.SideIndicator -eq "<=" )
        $LocalAddress = $c.InputObject.LocalEndPoint.Address
        $RemoteAddress = $c.InputObject.RemoteEndPoint.Address           
        $LocalPort = $c.InputObject.LocalEndPoint.Port
        $RemotePort = $c.InputObject.RemoteEndPoint.Port
        $name = [System.Net.DNS]::Resolve("$RemoteAddress")
        $name_canon = $name.hostname
        write "$RemoteAddress $name_canon : $RemotePort"
        $EventLog = new-object System.Diagnostics.EventLog("EstablishedTCPConnections") 
        $EventLog.Source = "$name_canon" 
        $infoevent = [System.Diagnostics.EventLogEntryType]::Information 
        $EventLog.WriteEntry("$LocalAddress established connection to $RemoteAddress ($name_canon) from Local Port: $LocalPort to Remote Port: $RemotePort",$infoevent,$RemotePort,01) 

start-sleep -m 100
$global:last_b = $b
} ## end function Established

function global:List-EstablishedTCP {do {EstablishedTCP} while (1)}

Sunday, February 8, 2009

This is a weird peice of code inspired by some syntax I found in Hristo Deshev's interesting book: "Pro Windows Powershell". Hristo talks about converting IDictionary objects to Hash Tables.  'PS' or 'get-process' uses the PID as the hash code for the process object. This allows a construct that produces a hash table with explict PIDs as hash keys. It is too late to figure out if this side-effect would have any value to anyone.

$script_block_ID = {ps | %{$_.ID} | Sort-object }
$dict = new-object Collections.Specialized.OrderedDictionary
$script_block_ID.Invoke() | %{$dict[(ps -id $_ | Select Name)] = $_.GetHashCode()}
write `r`n `$dict:
$hash = [hashtable]$dict
write `r`n `$hash:

@{Name=cmd}                    1364                                            
@{Name=alg}                    864                                             
@{Name=explorer}               3212                                            
@{Name=gvim}                   1852                                            
@{Name=wmiprvse}               1332                                            
@{Name=VCSExpress}             3980                                            
@{Name=wscntfy}                352                                             
@{Name=chrome}                 2724                                            
@{Name=svchost}                1536 

Friday, February 6, 2009

Enumerating TCP Connections

What I was looking for is a simple script to capture all new ("Established") connections.  This could use some improve since my code has some side-effects.  'Compare-object' subtracts the diff between two arrays: the reference set and the difference set. To run this I type this at a PS prompt:
  • function Est_do {do {Established} while (1)}
  • Est_do | out-file $pwd\Established.txt

function global:Established 
    $a = [System.Net.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties()
    if ($b -ne $null) {$last_b = $b}
    $b = $a.GetActiveTcpConnections()   | where{$_.State -eq "Established" }  
    if ($last_b -ne $null) 
        {$c = compare-object $last_b $b;
            if ($c.SideIndicator -eq "=>" ) {write $c.InputObject | ft -HideTableHeaders}       
   $global:last_b = $b
    start-sleep -m 250

[Established.txt] :


Thursday, February 5, 2009


Update 03/30/2012:
More work I did on this problem:

[back to original post...]

I spent some time seeing if Powershell could deliver some 'lsof' functionality easily with little luck. Few windows utilities do this now. Some exceptions are 'netstat -bno' (XPSP3) or tcpview.exe.  Powershell (or at least me with Powershell) can't do much with the TCPState interface despite the presence of static members:

PS > [System.Net.NetworkInformation.TcpState].GetMembers() | % {$_.Name}

This interface: [System.Net.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties()
was more useful:

$a = [System.Net.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties()
$b = $a.GetActiveTcpListeners() | Select Address,Port | Sort Port
$c = $a.GetActiveUDPListeners() | Select Address,Port | Sort Port
$d = $a.GetActiveTcpConnections() | Select LocalEndPoint,RemoteEndPoint,State | Sort State,RemoteEndPoint
write "TCP Listeners" $b | ft -auto
write "UDP Listeners" $c | ft -auto
write "TCP Active Connections" $d | ft -auto

PS >.\netstat.ps1
TCP Listeners

Address     Port
-------     ----      135  139  139      445   1027     3389

UDP Listeners

Address     Port
-------     ----    123  123  123  137  137  138  138      445      500 1900   1900 1900   2139   2683   2704     4500

TCP Active Connections

LocalEndPoint    RemoteEndPoint          State
-------------    --------------          -----    Established    Established    Established    Established   Established  Established   CloseWait