Friday, April 16, 2010

Display a PowerShell session’s RAM and CPU utilization in the Title Bar

So, I had a few other things I’ve cooked up this week that I was thinking about posting, but this was too much fun this morning.  Here’s a little bit of code you can stick in your powershell profile that will update the title bar with the current PowerShell session’s memory usage (working set, technically) and CPU utilization.

# Setup the objects for titlebar manipulation            
# Append a #1,#2,#(n-1) to the process name if there are n pre-existing processes with the same            
# name, as this is how the Performance Counter system references the instances.            
$psProcess = gps -id $PID            
$psInstances = (gps -Name $psProcess.name).count            
if ($psInstances -gt 1)            
{            
    $psName = "{0}#{1}" -f $psProcess.name,$($psInstances - 1)            
}            
else            
{            
    $psName = $psProcess.name            
}            
# Create the Performance Counter Object to track our sessions CPU usage            
$Global:psPerfCPU = new-object System.Diagnostics.PerformanceCounter( "Process","% Processor Time", $psName )            
# Get the first 'NextValue', which will be zero            
$psPerfCPU.NextValue() | Out-Null            
# Create a timer object and set the interval to 1 second            
$Global:psTimer   = New-Object System.Timers.Timer            
$psTimer.Interval = 1000            
# Update the window's title bar every time the timer object raises the            
# elapsed event            
Register-ObjectEvent -InputObject $psTimer -EventName Elapsed -Action {            
    $psInfo = Get-Process -id $pid            
    [int]$ws = $psInfo.workingset/1MB            
    [int]$cpu = $psPerfCPU.NextValue() / $env:NUMBER_OF_PROCESSORS            
    $Host.ui.rawui.WindowTitle = "$($CurrentUser.Name) $($Host.Name) $($Host.Version) | $((get-location).ProviderPath) | RAM: $ws MB CPU: $cpu%"            
} | Out-Null            
$psTimer.start()

The hardest part was getting the CPU utilization right, but these two posts spell out the details pretty well:
Happy Friday!

Friday, April 9, 2010

PowerShell’s Try/Catch/Finally and –erroraction Stop

Update: From an anonymous commenter, evidently error handing when using "-erroraction Stop" now works as one would expect in PowerShell version 3!  However, if you're still using version 2 the information below should help you out.

When planning for exception handling, I’ve recently learned that forcing execution to stop by setting $erroractionpreference to ‘Stop’ or by using the –erroraction common parameter requires some special handling.

First let’s see what doesn’t work even though it seems like it should.  Handling a normal terminating error is fairly straightforward:

image

Here we encountered an exception, got the exception’s type by inspecting the first element in the typenames member of the first error record’s exception’s base object, and then used that type name to catch the exception.  This worked whether or not we specified the –ea or –erroraction parameter.  This works because a ParameterBindingException is a terminating error.  However, let’s see what happens when we try the same thing with an error that isn’t of terminating error family:

image

Hmm, bugger.  We tried the same pattern, but this time it just doesn’t work.  But…why?  Without getting too long winded about it, I tried looking back through the automatic $error variable but couldn’t find an answer.  So I tried a different tactic:

image

Aha!  When we use –erroraction stop, the terminating exception isn’t the error that was encountered but an exception of type System.Management.Automation.ActionPreferencesStopException!  But…wait, if that’s true, how do we know what type of error was encountered?  Almost inexplicably the automatic variable $_ is set to the error record of the error that was encountered.  If you know why, please share in the comments or send me an e-mail.  Anyway, we can use that to re-throw the error as a terminating exception that can be caught and handled:

image

Basically we just wrap our command that makes use of the –erroraction stop inside two try/catch blocks.  The inner block is used to trap the ActionPreferenceStopException generated by the erroraction parameter.  In the inner catch block we throw the exception for the error that was caught which is then caught by the outer catch block statements and can the be handled.  So, let’s finish with a generic pattern that one could turn into a code snippet or something:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
try
{
  try
  {
    # Command that uses -erroraction stop or $erroractionpreference = 'Stop'
  }
  # Here we catch the Exception generated by the ErrorAction "Stop"
  # Only necessary if there is any processing we want to do if the
  # exception is of type ActionPreferenceStopExecution,
  # otherwise this block can be deleted
  catch [System.Management.Automation.ActionPreferenceStopException]
  {
    # Error Handling specific to ActionPreferenceStopException goes here
    # Rethrow the "real" exception as a terminating error
    Throw $_.exception
  }
  # All errors are caught and rethrown to the outer try/catch block
  # as terminating errors to be handled.
  catch
  {
    Throw $_.exception
  }
} 
# Here we can resume exception type handling as usual
catch #[System.Management.Automation.ItemNotFoundException]
{
  "Got it!"
}

And with that, Happy Friday!

Friday, April 2, 2010

Early preview of Group Policy Backup & Search Module

Alright, it’s taken WAY longer than I thought it would, but I finally have something I think is worth sharing in its very unfinished state.  First, what still sucks: the help is only slightly better than useless, the code itself is a bit jumbled and not well commented, not everything is formatted nicely when written to output, only 3 extensions (Software Installation, Scripts, and Policy/Registry – the big 3 for me) are implemented, and while the backup function works, you’re pretty much on your own for configuration at the moment.  That said, what does work is pretty cool (in my opinion):  You can search inside of your live group policy objects, as well as any archived XML Reports from Get-GPOReport, and get meaningful output!