More servicesWindows Live
HomeHotmailSpacesOneCare
 
MSN
Sign in
 
 
Spaces home  Time is an illusion. Lun...PhotosProfileFriendsMore Tools Explore the Spaces community

Time is an illusion. Lunchtime doubly so.

October 15

And now for a little Rossini

More music performed by the 1978 PCC Chamber Singers.  This time it's a little Rossini:
Accompanied again by Twyla Meyer and the soprano (heard around 4:20) is the spectacular Rebecca Sherburn.  This group was really quite impressive, I know that a number of the singers in this group have careers as singers.   Twyla is in great demand throughout LA and Bill Hatcher has had stellar career in choral music.  I feel extremely fortunate that I had the opportunity to learn from these amazing musicians.
October 11

more from PCC - 1978

Audite Nova by Lassus this time - it's a very silly piece. 
 
I remember really liking this piece and having a great time performing it.  Listening to it now, it seems so heavy, i suppose it should, with 6 on a part.  I've performed and listened to so much one-on-a-part that it's clear how much I've changed in the past 30 years.  Thank goodness for that - it would be horrible to think that I hadn't changed.
 
I've got a few more of these and also some recordings of the Pasadena Chorale from around 79 to 83.  I'll get them posted after I finish the Chamber Singers stuff
 
 
 
 
 
August 31

I love Twitter

I love the idea of twitter - I think it's the logical intersection between blogging and reduced attention spans.  I started to play about with it and I was frustrated with the way I needed to create entries.  Having a separate app to create twitter updates seemed wrong to me.  I don't want to change focus from my current shell to create an update and best case, I want to update my status automatically so I don't think about it, it just happens. 
 
I know that there are some command line tools to do this, but I I want a native solution for PowerShell, so I created a Send-TwitterStatus cmdlet to allow me to send updates directly from my shell.  Not only that, but I can use this cmdlet in other scripts to automatically push my activity to Twitter as well.  I created media player script and it seems like a natural thing to do is to push my playlist to Twitter so my friends can see what I'm listening to (if they want).  I have a line now in the script when I append an album to my playlist is a line that calls my cmdlet and pushes my update:
 
   Send-TwitterStatus "Adding to office playlist: $album" $credential
 
  • $album is the name of the album
  • $credential is a global variable that contains a PSCredential which is used by the cmdlet to authenticate with the Twitter service.  
I grabbed the Yedda.Twitter code to do the actual Twitter interaction and the rest is just the code to stitch the cmdlet together.  I also convert the XML results into a custom object so I can eventually create the appropriate formatting. 
 
Anyway - here you go. 
 
and the cmdlet code
My post http://jtruher.spaces.live.com/blog/cns!7143DA6E51A2628D!119.entry will show how to compile and install a snapin and use.
 
Next steps are to create the various twitter getters and create the format file so I can get activity directly from the shell.
 
 
 
 

More media - PCC Chamber Singers, 1978

It seems like the time just flies - it's been a couple months since I updated here, and I would like to post more often. 
 
In any event, I have another audio file to post!  This is the third of the Trois Chanson Britonnes Soir d'été.  My memory of the recording circumstances is a little fuzzy, since it was nearly 30 years ago, but I seem to remember that we did this recording around the end of the calendar year, and we hadn't yet learned the second chanson, so I only have this one (the last) and the first.
 
Conducted by Bill Hatcher and accompanied by the magnificent Twyla Meyer .
 
Here it is: Soir d'été
 
Some of the other pieces from this recording session are:
  • Audite Nova
  • I Heard a Voice
  • Deck the Halls
There are more, and I'll post them as I can
 
July 15

Tracing the script stack

It's not uncommon that after I've created a fairly complicated script after a while of using it, something bad happens that I wasn't expecting. And I would really like to know how I got to this state, so a stacktrace of my script would be really, really nice. Sadly, this isn't something that is a default behavior or PowerShell, but fortunately, this sort of thing is actually possible to do with just a little bit of script!

Most of the real world examples are more complicated than we really need to use to illuminate the problem.  So, I've created a simple example that is useful for discussion.

Take the following script:
# test-stacktrace1.ps1
param ( $startVal )
function func1
{
    param ( $startVal )
    1/$startVal--
    func2 $startVal
}
function func2
{
    param ( $startVal )
    1/$startVal--
    func3 $startVal
}
function func3
{
    param ( $startVal )
    1/$startVal--
}
func1 $startVal

When I run this script, depending on the value of my argument, the script will run or fail:

PS# c:\temp\test-stacktrace 5
0.2
0.25
0.333333333333333
PS# c:\temp\test-stacktrace1 2
0.5
1

Attempted to divide by zero.
At c:\temp\test-stacktrace1.ps1:18 char:7
+     1/$ <<<< startVal--

The message is ok - it tells me that I had a problem on the appropriate line in the script, but I don't know how I got there by looking at the message.  What I would really like to see is both the error and the way I got there.  Here are some examples of what I want to see:

This example is the normal behavior
PS# c:\temp\test-stacktrace2 3
0.333333333333333
0.5
1

This example will show what happens when an error occurs deep in the stack:
PS# c:\temp\test-stacktrace2 2
0.5
1
func3 : Attempted to divide by zero.
At c:\temp\test-stacktrace2.ps1:25 char:10
+     func3  <<<< $startVal
At c:\temp\test-stacktrace2.ps1:31 char:42+     trap { write-error $_; get-stacktrace  <<<< }
At c:\temp\test-stacktrace2.ps1:25 char:10+     func3  <<<< $startVal
At c:\temp\test-stacktrace2.ps1:17 char:10+     func2  <<<< $startVal
At c:\temp\test-stacktrace2.ps1:36 char:6+ func1  <<<< $startVal
At line:1 char:25+ c:\temp\test-stacktrace2  <<<< 2

Notice that I see the functions that I called on the way to this error - This way I can see the path of woe that generated the error - which means I have a much better chance of actually fixing the problem. 

Here's another example of what happens when an error occurs sooner in the stack, notice that we only see func1 and func2 calls:
PS# c:\temp\test-stacktrace2 1
1
func2 : Attempted to divide by zero.
At c:\temp\test-stacktrace2.ps1:17 char:10
+     func2  <<<< $startVal
At c:\temp\test-stacktrace2.ps1:23 char:42+     trap { write-error $_; get-stacktrace  <<<< }
At c:\temp\test-stacktrace2.ps1:17 char:10+     func2  <<<< $startVal
At c:\temp\test-stacktrace2.ps1:36 char:6+ func1  <<<< $startVal
At line:1 char:25+ c:\temp\test-stacktrace2  <<<< 1

And finally what happens when an error occurs right away, notice that we only see func1 in the stack:
PS# c:\temp\test-stacktrace2 0
func1 : Attempted to divide by zero.
At c:\temp\test-stacktrace2.ps1:36 char:6
+ func1  <<<< $startVal
At c:\temp\test-stacktrace2.ps1:15 char:42+     trap { write-error $_; get-stacktrace  <<<< }
At c:\temp\test-stacktrace2.ps1:36 char:6+ func1  <<<< $startVal
At line:1 char:25+ c:\temp\test-stacktrace2  <<<< 0

So, here's the code - and a brief discussion follows:

param ( $startVal )
function get-stacktrace
{
    trap { continue }
    1..100 | %{
        $inv = &{ gv -sc $_ myinvocation } 2>$null
        if ($inv) { write-host -for blue $inv.value.positionmessage.replace("`n","") }
        }
    exit
}
function func1
{
    param ( $startVal )
    trap { write-error $_; get-stacktrace }
    1/$startVal--
    func2 $startVal
}
function func2
{
    param ( $startVal )
    trap { write-error $_; get-stacktrace }
    1/$startVal--
    func3 $startVal
}
function func3
{
    param ( $startVal )
    trap { write-error $_; get-stacktrace }
    1/$startVal
}
# Main
func1 $startVal

Notice the addition of the "get-stacktrace" function:

function get-stacktrace
{
    trap { continue }
    1..100 | %{
        $inv = &{ gv -sc $_ myinvocation } 2>$null
        if ($inv) { write-host -for blue $inv.value.positionmessage.replace("`n","") }
        }
    exit
}
 

This function takes advantage of the fact that the PowerShell scoping rules allow you to inspect variables in different scopes from your current scope.  This isn't available via syntax, but it is available via the get-variable cmdlet (aliased to gv).  So our little get-stacktrace function just drills down our scopes looking for the myInvocation property which has the information about what line on the script we're on.  There are some other things that are going on.  The trap statement assures me that if I get any terminating errors that I ignore them and I've placed the call of gv in a script block - this allows me to really throw away any messages that get-variable may throw that aren't terminating errors.   Lastly, I want to be sure that my message is on a single line, so I replace the carriage returns with empty strings.

Notice also that each function now has a trap statement.  I think that this is generally good practice regardless, but these do two things.  First they write the error and then call the get-stacktrace function.  We need to write the error because the get-stacktrace function is going to exit, so if we didn't have this write-error we wouldn't actually see what the error was, just the stack trace which isn't enough info.

So, if you've got a complicated script and you would really like to discover how you got where you are, I hope this little bit of script will help!

Jim

 

View more entries
 
Updated 4/17/2008