# Wednesday, May 16, 2007

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

posted on Wednesday, May 16, 2007 7:02:10 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [0] Trackback
# Sunday, May 13, 2007

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!

posted on Sunday, May 13, 2007 8:09:16 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [1] Trackback
# Tuesday, April 17, 2007

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.

posted on Tuesday, April 17, 2007 9:07:39 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [0] Trackback
# Wednesday, March 07, 2007

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.

 

posted on Wednesday, March 07, 2007 10:42:21 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0] Trackback
# Monday, January 29, 2007

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."

posted on Monday, January 29, 2007 6:24:05 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0] Trackback
# Saturday, January 27, 2007

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.

posted on Saturday, January 27, 2007 11:59:50 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0] Trackback
# Friday, January 05, 2007

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

posted on Friday, January 05, 2007 3:00:46 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0] Trackback
# Saturday, November 04, 2006

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

posted on Saturday, November 04, 2006 9:40:42 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [0] Trackback