Skip to content
Archive of posts filed under the Uncategorized category.

My new favorite cmdlet: set-strictmode

If you’ve ever written Visual Basic or VB.Net code, you’re aware that it’s highly recommended that you use “Option Strict” in all of your code.  Similarly, Perl scripters have a “use strict” that comes highly suggested.

The idea of these options is that there’s quite a bit of flexibility built into these languages, and sometimes that flexibility backfires on you.  Using these options actually limits the flexibility of the languages in question in ways that help coders to keep from making certain types of mistakes in their code.  Writing code professionally in VB.Net (you may scoff, but it happens quite a lot) or Perl (it’s not my language of choice, but again, there’s a lot out there) without using these options is not a good idea at all.

I’ve been writing code in PowerShell for about 2 years, and have probably written about 10,000 lines, mostly code that’s used on a daily basis.  I’ve read several PowerShell books, online tutorials, and watched several webcasts.  I may have not been paying attention, but I’ve completely missed any emphasis on the analogous option in PowerShell, “set-strictmode”.  One of my co-workers asked if there was something like this in PowerShell, and I found it almost instantly.  Google, and the PowerShell help file both explain how the cmdlet works.  He and I started using it, and to our dismay, found dozens of errors in code that we had been trusting, in some case, for over a year.

First of all, let me explain that I’m not complaining that there’s not any information about how set-strictmode works in the “ecology” of the PowerShell community.  I’m confident that each book and tutorial explains how this cmdlet works.  What I’m concerned about is how I could have read as much as I have from as many people are talking about PowerShell without hearing anyone (or everyone) shouting at the top of their collective voices, “Add this to your profile…it will save you countless hours and tears in the long run”.  Hopefully, I’ve just missed it, and everyone has been saying this all along.  In case this has not been the case, let me say:

Add set-strictmode to your profile.

It will save you countless hours and tears in the long run.

So….how do I use set-strictmode, and what does it help with?  First, to turn on “strict mode” you need to decide which version of strictmode you want.  The options are:

Version Effect
1.0 References to uninitialized variables(except in a string) are errors
2.0
  • References to uninitialized variables(including in a string) are errors
  • References to undefined properties are errors
  • Calling a function using method-call syntax is an error
  • ${} (an un-named variable) is a syntax error
Latest Uses the most strict mode available for this version of PowerShell.  (Currently the same as 2.0)

I would advise that you use “set-strictmode –version Latest” in your profile.

Let’s look at the different restrictions.  First, if you’ve written any PowerShell scripts, you’re aware that you don’t have to declare your variables.  That’s a “good thing”, and strictmode 1.0 doesn’t change that in any way.  What it does do is make sure that you’re not retrieving values from variables you haven’t assigned anything to.  Here’s some sample code that strictmode will choke on.

$servername=read-host -prompt "Enter name of server"
$wmi=get-wmiobject -class Win32_Service -computername $server_name

This is a pretty simple example, but it’s almost certain that sooner or later you’ll typo a variable name in a script.  Strictmode will help keep you from getting in this kind of trouble.  With strictmode Version 1.0, you won’t be warned about using uninitialized variables in double-quoted string, e.g. “Server=$server_name”…(they’ll be replaced with $null).  Version 2.0 will cause references to uninitialized variablesinside strings to be an error as well.

Here’s an example of code that illustrates property restrictions in StrictMode 2.0.

$servername="Server123"
$length=$servername.lenght

I would write up an example of using the method-call syntax for a function, but Thomas Lee just blogged about this in his blog Under the Stairs.

The final “restriction” in strict mode 2.0 says that you can’t have a variable with no name.  The syntax ${varname} is a way of expressing $varname, when varname contains characters that are not generally allowed in variable names.  I haven’t ever had a really convincing use for this syntax (I’ve thought about using it to associate variables with filenames using the full path as the variable name, but it seems like a dictionary would be cleaner).

I should note that Lee Holmes has done a great thing in his recently published PowerShell Cookbook V2.  Each script in the cookbook starts with “set-strictmode –version Latest”.   In my opinion, this is a best practice.

If you’re just now hearing about set-strictmode for the first time, and already have a body of powershell scripts in your toolbox (I’m in this category), I’d recommend the following steps:

  1. Add set-strictmode –version Latest to the profile on the machine you do your script development on
  2. Add set-strictmode –version Latest  to any scripts you create from this time forward
  3. Add set-strictmode –version Latest to scripts that you have tested to make sure they comply with strictmode.

I’m going to avoid turning on strictmode on servers that I’m running PowerShell on for now, because I’m sure stuff will break.  I’m slowly refurbishing scripts as I run them on my development box and see the strictmode errors pop up, and since set-strictmode is a scoped change (if you set it in a script or function, it reverts to the old setting when you exit the script or function), I can take advantage of it in a script-by-script basis.

If you are just starting to build a PowerShell script library, I would recommend turning strictmode on in the profile on every machine that you run PowerShell scripts.  You’ll be glad you did.

Hopefully this was not too much of a rant.  Please let me know what experiences you’ve had with with set-strictmode.

Mike

  • Digg
  • Slashdot
  • Reddit
  • Tumblr
  • Delicious
  • Twitter
  • Google Bookmarks
  • StumbleUpon
  • Technorati Favorites
  • Google Reader
  • Share/Bookmark

PowerShell and MongoDB

I recently saw this link on using NoSQL with Windows.  Now, I’m a SQL Server DBA, so I haven’t really had any reason to use NoSQL.  I was curious about how easy it was going to be to set up and if I could get it working with PowerShell.

I selected MongoDB from the list because it looked more like something that would be used on smaller-scale projects.

I then googled “MongoDB PowerShell” and found this link from Doug Finke about using MongoDB with PowerShell (and F#, which is another “cool thing” I haven’t managed to find a need for).  Doug links to another article which explains setting up MongoDB and an open-source .Net driver for MongoDB called mongo-csharp.  He then follows up with a straight-forward script showing simple usage of MongoDB.  It looks like an almost literal translation of the C# code from the article he references.  With those in hand, I thought it was going to be a slam dunk.

It was, but I had a few hurdles to get over before I could get it working.  There weren’t any problems with the code;  it was written about a year ago, so it was using PowerShell 1.0 and an older version of mongo-csharp.  I had to update the script in a couple of places to make it work.  I probably wouldn’t even write it up, given how minor the changes are, but I was somewhat disappointed with the number of hits I got for “MongoDB PowerShell”.

Here’s the updated script:

add-type -Path .\MongoDB.Driver.dll

$mongo=new-object mongodb.driver.mongo
$mongo.connect()
$db=$mongo.GetDataBase("movieReviews")
$movies=$db.GetCollection('Movies')

$movie=new-object Mongodb.driver.document
$movie['title']='Star Wars'
$movie['releaseDate']=get-date
$movies.Insert($movie)

$spec=new-object Mongodb.driver.document
$spec['title']='Star Wars'
$movies.FindOne($spec)

The two changes were

  1. added the parameter name (-path) to add-type, since the default param is looking for an assembly name, not a path to a DLL
  2. changed $mongo.GetDB to $mongo.GetDatabase to reflect a change in the driver

Worked fine. Not sure how I’ll use this, but if I need to, I know I can from PowerShell.

-Mike

  • Digg
  • Slashdot
  • Reddit
  • Tumblr
  • Delicious
  • Twitter
  • Google Bookmarks
  • StumbleUpon
  • Technorati Favorites
  • Google Reader
  • Share/Bookmark

The Identity Function

In mathematics, an identity function is a function that returns the arguments that are passed to it unchanged.  While the concept of an identity function is quite often useful in formulating proofs, it is not something that I ever expected to use in a programming environment.   Here’s the identity function written in PowerShell:

function identity{
    return $args
}

The surprising thing about this function is that it’s actually pretty useful. PowerShell’s array literal syntax is considerably more involved than it’s argument syntax. Using this function lets us do this:

identity arg1 arg2 arg3

instead of this:

@('arg1','arg2','arg3')
  • Digg
  • Slashdot
  • Reddit
  • Tumblr
  • Delicious
  • Twitter
  • Google Bookmarks
  • StumbleUpon
  • Technorati Favorites
  • Google Reader
  • Share/Bookmark

New Versions of PowerShell Community Extensions (PSCX) and SQL PowerShell Extensions (SQLPSX)

In case you haven’t heard, the PowerShell Community Exetensions (PSCX) and SQL PowerShell Extensions (SQLPSX) projects have both recently released version 2.0 (and each followed shortly after with quick bug fixes). Both 2.0 releases are module-based and include advanced functions to solve lots of frequently encountered problems. If you haven’t ever used these toolsets, I would recommend giving them a try.

PowerShell Community Extensions

SQL PowerShell Extensions

  • Digg
  • Slashdot
  • Reddit
  • Tumblr
  • Delicious
  • Twitter
  • Google Bookmarks
  • StumbleUpon
  • Technorati Favorites
  • Google Reader
  • Share/Bookmark

Passing Predicates as Parameters in PowerShell

This is just a quick trick that I figured out today. I had a process that manipulated a dataset, and I needed to be able to change the process to allow me to filter the data that was processed. Also, it wasn’t clear exactly what kind of filter would specifically be needed in any given scenario.

Normally, I would just filter the data using where-object and pass it in to the function in question. The problem here was that the data retrieval was somewhat cumbersome, and I didn’t want to push that complexity outside of the function. And since the filtering criteria wasn’t clear-cut, I couldn’t (and didn’t want to) use a bunch of switches and parameters along with a nest of if/else conditions.

What I wanted, was to pass a predicate (an expression that would evaluate to true or false depending on whether I want a row in the dataset) in to the function. Essentially, I wanted to insert a where-object into the middle of the function.

Amazingly, PowerShell allows me to do that. The code looks a bit strange to me at first, but it works very well and isn’t complicated at all.

Here’s an example:

function process-data{
Param( [scriptblock]$filter = {$true})

	#retrieve the data

	#filter the data
	$data = $data | where-object $filter

	#process the data
}

process-data -filter {$_.UpdatedDateTime -gt (get-date '1/1/2010')}

It’s not earth-shattering, but I think this will come in handy in several places for me.

Let me know what you think.

-Mike

  • Digg
  • Slashdot
  • Reddit
  • Tumblr
  • Delicious
  • Twitter
  • Google Bookmarks
  • StumbleUpon
  • Technorati Favorites
  • Google Reader
  • Share/Bookmark

Checking a Field for NULL in PowerShell

It’s been a long time (over 2 months) since I last posted.  I’ll try to get back into a rhythm of posting at least weekly.  Anyway, this is something that occurred to me at work when writing a script.

I usually avoid nullable columns, but sometimes date fields make sense to be null (rather than use sentinel values like 1/1/1900).  In this case, I had a nullable date column and I needed to check in PowerShell whether the field was in fact null or not.  In SQL, I would have just used an IS NULL, or used the IsNull() function to replace the null value with something a little easier to deal with.  My first (feeble) attempt was to do this:

if (!$_.completedDate){
# it’s null
}

Unfortunately for me, that doesn’t work.  Next, I used this (which worked, but wasn’t very satisfactory either):

if ($_.completedDate.ToString() -eq ''){
# it’s null
}

Realizing that I was being stupid, I googled “PowerShell SQL NULL and after looking at several pages which didn’t really address the issue, I found this. A little work to change it into a function, and voilà.

function is-null($value){
  return  [System.DBNull]::Value.Equals($value)
}

A few quick tests and this is what I wanted. Now, my code looks like this:

if (is-null $_.completedDate){
# it’s null
}

I find it hard to believe I haven’t written this function before (or seen it).

By the way…be watching the SQL PowerShell Extensions project.  Chad released version 2.1, which includes SQL mode for the ISE (really nice).  I know he and several others are collaborating on an update which should be out sometime soon.

-Mike

  • Digg
  • Slashdot
  • Reddit
  • Tumblr
  • Delicious
  • Twitter
  • Google Bookmarks
  • StumbleUpon
  • Technorati Favorites
  • Google Reader
  • Share/Bookmark