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.com.  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: 

    $local_out=
    "last_netblock",
    "netblock",
    "State" 

    $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
    $Global:locals_out=
    {
    $State
    $last_netblock
    write .
    $netblock
    }

 ## Debug
    write $Locals_out.Invoke()

to be continued...

No comments: