Time For A Change

by oising 12. August 2008 14:03

It’s getting harder to post useful scripting tips for PowerShell these days as there are so many talented hardcore scripting bloggers around. My day to day is job is not system/network/server administrator; I’m a .NET developer, having started the C# habit about eight or nine years ago with the early CLR 1.0 beta. So, from here on in, I’ve decided that a better direction for me to take from now on is that of a PowerShell developer,  as opposed to a scripter. There are very few (if any?) dedicated PowerShell developer blogs around, and so I figured I should try to fill that gap as best I can. I have a not insignificant amount of experience writing providers, cmdlets and other widgety bits, so it’s a good time to share my experiences. Of course, my way is not “the” way, so please reply with your own experiences/advice/mocking/whatever. ;-)

That said, I am not eschewing scripting altogether – I have some stuff in the pipeline (har-har) concerning areas I’m interested in, like eventing and jobs/remoting.

Tags:

.NET | Cmdlets | Monad | PowerShell | Providers | PSCX | PSEventing | SharePoint | SnapIns

PSEventing 1.1 For PowerShell 1.0 Final Release

by oising 6. June 2008 01:20

I took a few hours yesterday to "tidy up my room" so to speak, so I built a nice MSI installer, updated the help, CodePlex Wiki and examples and closed all bugs. This is probably the final release now that PowerShell 2.0 CTP2 has introduced support for eventing, so thanks for all the support.

New Features

  • Multiple named queue support and default queue with -QueueName parameter
  • Better COM support, window message pumping etc.
  • NoFlush / Peek parameter support for queue reading
  • Get-EventQueue command added for viewing queues and their message counts.

Cmdlet Name Changes

  • Get-Event -> Read-Event
  • Connect-EventListener -> Connect-Event
  • Disconnect-EventListener -> Disconnect-Event

Additionally, several niggling bugs closed (including the one where read-event -wait would return immediately with no events).

http://www.codeplex.com/pseventing

For an advanced example: Foreground / Background Swappable Downloads In PowerShell.

Tags:

CodePlex | Monad | PowerShell | PSEventing

My PowerPoint slides from PowerShell Virtual User Group #2

by oising 14. December 2007 16:04

In case anyone is interested, here are my slides in PowerPoint PPTX format from the most recent PS Virtual User Group. It covers the new Path handling infrastructure for PscxCmdlets in the upcoming PowerShell Community Extensions 1.2 and some brief information on my PowerShell Eventing snap-in for PowerShell.

psvug2_oisin_grehan.zip (152 KB)

(updated to a zip: it appears DasBlog will not serve pptx files?)

Tags:

.NET | Monad | PowerShell | PSCX | PSEventing

Foreground/Background Swappable Downloads in PowerShell

by oising 5. December 2007 12:47

Here's another interesting use for my PowerShell Eventing Snap-In, where I'm simulating unix-style foreground/background tasks. In this case, the task is a large download using System.Net.WebClient. Just dot-source the script below and start a download using the Start-Download function, passing the url to the large file and the local path where to save your file (be sure to fully qualify the save path). The download will start immediately and show a progress bar with bytes remaining and a percentage, however you can hit Ctrl+C at any time and the download will continue in the background. You can get back to PowerShell tasks, and bring back up the progress bar by invoking Show-Progress at any time. Use Stop-Download to cancel the currently active download. Only one download can be active at a time, but this could easily be extended to support a pool of downloads (using multiple WebClient objects).

downloads.ps1 (1.85 KB)

  1. #requires -pssnapin pseventing  
  2.  
  3. function Stop-Download {  
  4.     $wc.CancelAsync()  
  5. }  
  6.  
  7. function Start-Download {  
  8.     param(  
  9.         [uri]$Url = $(throw "need Url."),  
  10.         [string]$Path = $(throw "Need save path.")  
  11.     )  
  12.  
  13.     # initialise webclient  
  14.     if (-not $global:wc) {  
  15.         $global:wc = New-Object System.Net.WebClient  
  16.         $var = get-variable wc  
  17.         Connect-EventListener -Variable $var `  
  18.             -EventName DownloadProgressChanged, DownloadFileCompleted         
  19.     }  
  20.  
  21.     if ($wc.IsBusy) {  
  22.         Write-Warning "Currently busy: Please cancel current download or wait until it is completed." 
  23.         return 
  24.     }  
  25.       
  26.     $wc.DownloadFileAsync($url, $path, $path) # last is userstate  
  27.     Write-Host "Download started. Ctrl+C to continue in background." 
  28.     Show-Progress  
  29. }  
  30.  
  31. function Show-Progress {  
  32.     if (-not $wc.IsBusy) {  
  33.         # possibly already completed, clear queue  
  34.         get-event | Out-Null 
  35.         "No active download." 
  36.         return 
  37.     }  
  38.       
  39.     Start-KeyHandler -CaptureCtrlC  
  40.       
  41.     trap [exception] {  
  42.         Stop-KeyHandler  
  43.         Write-Warning "error" 
  44.         $_ 
  45.         return 
  46.     }  
  47.       
  48.     $exiting = $false 
  49.       
  50.       
  51.     while (-not $exiting) {       
  52.         $events = @(Get-Event -Wait)          
  53.         $event = $null;  
  54.           
  55.         # skip to last event  
  56.         foreach ($event in $events) {  
  57.             if ($event.Name -eq "CtrlC") {  
  58.                 break;  
  59.             }  
  60.         }         
  61.           
  62.         switch ($event.Name) {  
  63.             "DownloadProgressChanged" {  
  64.                 $r = $event.args.BytesReceived  
  65.                 $t = $event.args.TotalBytesToReceive  
  66.                 $activity = "Downloading $($event.args.userstate)" 
  67.                 $p = [math]::Ceiling(([double]$r / $t) * 100)  
  68.                 Write-Progress -Activity $activity -PercentComplete $p `  
  69.                     -Status ("{0} of {1} byte(s)" -f $r,$t)  
  70.             }  
  71.             "DownloadFileCompleted" {  
  72.                 Write-Progress -Activity DownloadComplete -Completed  
  73.                 "Complete." 
  74.                 $exiting = $true 
  75.             }  
  76.             "CtrlC" {  
  77.                 "Switching to background downloading. Show-Progress to move to foreground." 
  78.                 $exiting = $true 
  79.             }  
  80.         }         
  81.     }  
  82.     Stop-KeyHandler  

Tags:

.NET | Monad | PowerShell | PSEventing

Using Windows Forms Controls in PowerShell #1: ListBox

by oising 2. December 2007 21:48

Using Windows Forms controls in PowerShell is a tricky thing, because it only supports very simple event listboxhandling. However, some time ago I wrote a Snap-In to allow anyone to work with .NET events, even asynchronous ones. You can download it from my PSEventing CodePlex project; it comes with full help via the normal PowerShell mechanisms of -? and get-help. Examples are also available online on how to use the project for more complex scenarios. Here's simple demonstration of autogenerating a listbox control filled with choices given as arguments to a simple script:

  1. # as simple as 1,2,3 :-)  
  2. $choice = .\get-choice.ps1 "one","two","three" 

And here is the source to the get-choice.ps1 script itself. This requires PSEventing 1.0 or 1.1 Beta.

  1. #requires -pssnapin pseventing  
  2.  
  3. # http://www.codeplex.com/pseventing (1.0 or 1.1)  
  4.  
  5. param([string[]]$choices = $(throw "please supply a string array of choices"))  
  6.  
  7. if ($choices.length -eq 0) {  
  8.     Write-Warning "cannot be a zero length array." 
  9.     return 
  10. }  
  11.  
  12. # initialize form  
  13. $form = new-object windows.forms.form  
  14. $form.Text = "Choose..." 
  15. $form.MinimizeBox = $false 
  16. $form.MaximizeBox = $false 
  17. $form.AutoSize = $true 
  18. $form.AutoSizeMode = "GrowAndShrink" 
  19.  
  20. # initialize listbox  
  21. $listbox = new-object windows.forms.listbox  
  22. $choices | % { [void]$listbox.items.add($_) }  
  23.  
  24. $form.controls.Add($listbox)  
  25.  
  26. # catch a choice in the listbox (remove -verbose for quiet mode)  
  27. Connect-EventListener -VariableName listbox -EventName SelectedIndexChanged -Verbose  
  28.  
  29. # catch someone closing the form (remove -verbose for quiet mode)  
  30. Connect-EventListener -VariableName form -EventName Closed -Verbose  
  31.  
  32. $form.Show()  
  33.  
  34. # wait for an event while performing sendmessage pumping (or ctrl+c to exit)  
  35. $event = Get-Event -Wait  
  36.  
  37. # don't pollute pipeline (remove in production)  
  38. write-host ($event | ft -auto | out-string)  
  39.  
  40. $form.Dispose()  
  41.  
  42. $choice = $listbox.SelectedItem  
  43.  
  44. # clean up; event listeners will be automatically unhooked ;-)  
  45. $form = $null 
  46. $listbox = $null 
  47.  
  48. # return chosen item, or $null if the form was closed  
  49. if ($event.Name -eq "SelectedIndexChanged") {  
  50.     $choice 
  51. } else {  
  52.     $null # cancelled  
Have fun!

Tags:

.NET | Monad | PowerShell | PSEventing

About the author

Oisin Grehan lives in Montreal, Canada and builds all sorts of crap for all sorts of people.

Month List

Page List