PSEventing 1.0 Released

PSEventing 1.0 Released

Trap and respond to synchronous & asynchronous .NET events within your powershell scripts with this easy to use suite of cmdlets.

What's new?


  • A PSEvent object's Source property now contains the PSVariable wrapping the original object which generated the event. This resolves scoping issues with 0.5 whereby it wasn't always possible to reach the original sender by variable name (using get-variable).
  • New-Event cmdlet added for inserting user-generated "events" into the queue. This cmdlet allows attaching an abitrary object payload which is available in the PSEvent's Args.Data property.
  • All event handlers are now AUTOMATICALLY unhooked if the original PSVariable goes out of scope! No more phantom events continually generated if you forget to use the explicit "Disconnect-EventListener" and lose your reference. Simply null out a variable or let it disappear into the scopeless void!
  • and finally, some bugfixes, as listed on the release page.

Pick it up from CodePlex, includes source: http://www.codeplex.com/PSEventing/

 

The straw that broke the CAML's back

I like to see myself as a competent SharePoint developer having worked with it since beta 1 on various large scale projects, but it always bothered me that there were large swathes of it on which I was no expert, primarily due to one thing: CAML. It disgusts me - in fact, my brain downright rejects it. Every time I have to create some markup for a simple SPQuery, I have to look pull out the SDK reference material. CAML for me symbolizes everything bad that came out of the 1998-2001 "XML revolution," where absolutely everything had to be xml/xslt driven, where all wisdom concerning the separation of presentation and data disappeared in a puff of <smoke />.

It's not often that you see a new technology and you just "get it." No thinking required; instant grokkage. I thought I "got" LINQ, but it wasn't until today that I truely got it. So, I'm not sure if this qualifies as a "straw" as per the metaphor used in the title, perhaps a full-on hulking haybale would be more apt. Enter Bart de Smet's savegely impressive LINQ to SharePoint project on CodePlex. No more of the nausea-inducing verbosity that is CAML; just plain old C# 3.0.

New wrapper scripts to make using PSEventing easier

I've included some handy wrapper functions to make working with events and scriptblocks a bit easier - download the example script called "event handling wrapper functions" from the Releases page.

  • Add-EventHandler : Automatically run a scriptblock when the provided event occurs on a given variable (when inside Do-Events loop)
    • Add-EventHandler [-Variable] <PSVariable> [-EventName] <String> [-Script] <ScriptBlock>
  • Remove-EventHandler : Remove all bindings for the specific event from the given variable.
    • Remove-EventHandler [-Variable] <PSVariable> [-EventName] <String>
  • Do-Events : Much like VB's DoEvents command, this function puts PowerShell into a waiting state and will call your ScriptBlocks when your configured events occur. Use Ctrl+C to exit.
    • Do-Events [-ExitImmediately] <Boolean>


NOTE: your ScriptBlocks will only be called if you're inside a Do-Events loop.

1# Add-PSSnapin PSEventing
 
2# $fsw = new-object system.io.filesystemwatcher
3# $fsw.Path = "c:\temp"
4# $fsw.EnableRaisingEvents = $true
 
5# Add-EventHandler (get-variable fsw) deleted {
            param([System.Management.Automation.PSVariable]$variable, [EventArgs]$args)
     ... do stuff ... }
 
6# Do-Events $false

an example how to wire up an event using the wrapper scripts

Wondering how to handle .NET events in PowerShell?

Nrgghg,  I feel another PowerShell project coming on ...  enter PowerShell Eventing 0.5 Beta! With the magic of lightweight codegen, aka LCG, a smidgeon of reflection (well, quite a bit) and some inspiration, I managed to cough up this latest project.

While you cannot directly bind scriptblocks as eventhandlers, you can automatically route events in realtime to a background queue and deal with them in your time with a special Get-Event cmdlet. There is a sample walkthrough on the home page of the Wiki, and you can download a Sql backup script which shows progress reporting, all in script!

PS 1# Add-PSSnapin PSEventing                                                                      
PS 2# $wc = new-object system.net.webclient                                                        
PS 3# get-eventbinding -IncludeUnboundEvents | ft -auto                                            
                                                                                                                        
VariableName   EventName               TypeName  Listening                                                              
------------   ---------               --------  ---------                                                              
wc             Disposed                WebClient     False                                                              
wc             DownloadDataCompleted   WebClient     False                                                              
wc             DownloadFileCompleted   WebClient     False                                                              
wc             DownloadProgressChanged WebClient     False                                                              
wc             DownloadStringCompleted WebClient     False                                                              
wc             OpenReadCompleted       WebClient     False                                                              
wc             OpenWriteCompleted      WebClient     False                                                              
wc             UploadDataCompleted     WebClient     False                                                              
wc             UploadFileCompleted     WebClient     False                                                              
wc             UploadProgressChanged   WebClient     False                                                              
wc             UploadStringCompleted   WebClient     False                                                              
wc             UploadValuesCompleted   WebClient     False                                                              
                                                                                                                                                                                                                                        
PS 4# Connect-EventListener wc disposed -verbose                                                   
VERBOSE: Target is a WebClient                                                                                          
VERBOSE: Now listening for 'disposed' events from $wc                                                                   
PS 5# $wc.Dispose()                                                                                
PS 6# get-event | ft -auto                                                                         
                                                                                                                        
Occurred             Source      Name     Args                                                                          
--------             ------      ----     ----                                                                          
5/13/2007 8:04:20 PM variable:wc Disposed System.EventArgs                                                              
                                                                                                                                                 

Have fun!

How to unset the readonly option on a psvariable

I had an interesting problem today, I wanted to temporarily set a powershell variable to "readonly." So, I tried the obvious, and expected it to fail (it did):

PS E:\projects\powershell> $p = 7                                                                                       
PS E:\projects\powershell> (gi variable:p).Options = "readonly"                                                         
PS E:\projects\powershell> (gi variable:p).Options = "none"                                                             
Exception setting "Options": "Cannot overwrite variable p because it is read-only or constant."                         
At line:1 char:17                                                                                                       
+ (gi variable:p).O <<<< ptions = "none"                                                                                

Of course it seems pretty obvious in hindsight that this would fail, but why do they provide both "const" AND "readonly" choices for variables? well, after some spelunking with the excellent Reflector (my first choice these days, I find it easier than navigating around the msdn behemoth), I found the answer:

internal void SetOptions(ScopedItemOptions newOptions, bool force)
{
    using (IDisposable disposable = tracer.TraceMethod(newOptions))
    {
        if (this.IsConstant || (!force && this.IsReadOnly))
        {
            SessionStateUnauthorizedAccessException exceptionRecord = new SessionStateUnauthorizedAccessException(this.name, SessionStateCategory.Variable, "VariableNotWritable");
            tracer.TraceException(exceptionRecord);
            throw exceptionRecord;
        }

E.g, if the variable is not a constant, you can force the change:

PS E:\projects\powershell> set-item variable:p $p -force                                                                
PS E:\projects\powershell> (gi variable:p).Options                                                                      
None                                                                                                                    

This resets the "readonly" bit.

PSCX 1.1 Released!

Well, we've done it! Head on over to grab the latest release of PowerShell's most advanced and feature-rich snap-in!

http://www.codeplex.com/PowerShellCX

I'm pretty proud of this one. I wrote the archive cmdlets write-zip, write-bzip2, write-tar and write-gzip. I also wrote a general purpose assembly resolver cmdlet, resolve-assembly, and also an AssemblyCache provider; yes, the GAC.

 

Computer Acronyms & Interview Techniques

Sometimes when I interview people for a technical position, I throw a couple of acronyms at them to see if they can expand them and even better, explain them. I've been challenged on the validity of this as a "filtering" technique to catch out the bullshitters; I'm convinced it's a good way of checking on someone's level of [claimed] knowledge. It can let you see how long they've been in the game -- and at what level they sat in the nerd stack -- if you throw something old at them like SNMP or UUCP. You can also see how current they are with trends with ones like SOA, LINQ or TDD.

I think the funniest answer I got was for SCSI: "System Can't See It."

PowerShell Community Extensions

Now that I'm involved in two PowerShell projects, it's probably only fair that I should spend a little time talking about the non-sharepoint one. The PowerShell Community Extensions -- or PSCX for short -- consists of a group of maybe half a dozen people who are passionate about Monad (there! he said it again! stone him!) who are trying to fill in some gaps in the support for everyday operations that we're used to using from the good old fashioned command prompt. Yes, you can use ping.exe from powershell, but it's not native and if you want to use any of the output you must revert to old-school string parsing a la awk or sed. There's nothing wrong with awk or sed, but it's not the "PowerShell Way." Everything should be an object, right Mr Gosling?

For our upcoming release 1.1, in addition to some reimplementations of existing DOS-based tools, there are some pretty cool extras such as an enhanced Tab-completion system. This is implemented in c# for performance -- as opposed to the current script-based approach -- and can tab complete much more things such as static members, types, and can partially evaluate statements. There are also symlink and filesystem commands, and my contribution: bzip2, gzip, tar and zip creation cmdlets.

SharePoint Provider for PowerShell v1.0

So, happy new year everyone (read: both of you reading this blog) -- fyi, there's a powershell v1.0 binary compatible build of my SharePoint PSProvider up on codeplex now. I also filled out the Wiki with some information that was sorely lacking.

http://www.codeplex.com/PSSharePoint

New home for SharePoint Provider

As a sign that I'm trying to ramp up development (especially getting a MOSS 2007 layer working), I've snagged me a spot on the codeplex for this code. Feel free to ask for features, provide ideas, critique whatever on the forums provided. I'm also working on an ArchivePSProvider which will allow navigation of Zip and Tar files as hierarchical stores as well as providing some pipe-friendly cmdlets for tar/gzip/zip, e.g.  get-childitems -inc *.log | out-tar | out-gzip

About the author

Irish, PowerShell MVP, .NET/ASP.NET/SharePoint Developer, Budding Architect. Developer. Montrealer. Opinionated. Montreal, Quebec.

Month List

Page List