Automating the world one-liner at a time…
When we designed PowerShell we decided that we wanted to have Shell syntax and semantics because this is what was missing from the market and because it supports the ad hoc development practice that is so suited to the needs of administrators. We also observed that most shells ran out of power pretty quickly and people had to throw away their scripts and start from scratch with a more powerfull scripting language like Perl. Sadly, sometimes those environments ran out of power as well and people had to throw them away and start from scratch using a systems programming language like C++. We looked at those things and decided that PowerShell ALSO had to be a great scripting language and be decent systems programming language. This is the orgin of our quest to have the widest possible dynamic range.
You don't need to think about this very long to realize that we were going to run into some problems. Boy did we! That said, I was surprised at how many would disappear if you resisted the urge to say, "choose between Shell and Programming". If you worked hard, got creative, and struggled with it, most of these apparent conflicts would give way to a great solution. That only worked so far and there were times when we had to choose and in general (but not always), we favored Shell over Programming.
One of those areas was error generation. Shells are like the grandparents that you see a couple times a year - they love you and forgive almost anything. Access a variable that doesn't exist? We're not going to complain.Access a property on a variable that doesn't exist? That's OK.
Now we're not idiots so if you try to SET a property on a variable that doesn't exist or call a method that doesn't exist, we complain.
These are great semantics for ad hoc programming but not for more rigourous programming and they can even burn you for ad hoc programming as well. If you misspell a name, things will run fine but you won't get what you want. This is why we introduced STRICT MODE. In V1, we introduced a command SET-PSDEBUG -STRICT which puts PowerShell into strict mode where we complain if you access a variable that does not exist.
That is really great but it has 2 problems. It is not all that strict and it sets the mode for the entire process. Roman Kuzmin brought this up this morning in a comment on the Select-Grid script. He pointed out that it made a call to SET-PSDEBUG -STRICT and warned that this was inappropriate for most environments because it causes your ad hoc scripts to start failing. Get it? So imagine have a sloppy ad hoc script that has these issues but works fine for your purposes. You then dot source Select-Grid and that script now starts throwing errors. Now imagine that it's not just one script but dozens of scripts all throwing errors where they didn't use to. A purist would say that those are broken scripts and you need to fix them all. A non-purist would say, "ish!!!" (an homage to my midwest friends).
If you look at the name, you'll see that we were actually pretty explicit about it. This is a technique that is useful for DEBUGGING your script. In V2, we introduce a new cmdlet that addresses many of the problems Set-StrictMode. This provides strict semantics in a way that does not affect the entire process AND it adds a number of new cases to check. We added these cases based upon the complaints we recieved and the errors we saw. That means 2 things: 1) Yes we listen to you. Please complain complain complain. We LIKE complaints. Every complaint is an opportunity for us to generate the worlds best product.2) If we didn't cover the case that keeps burning you - see bullet #1We now consider it best practice to use this for scripts of any consequence. Certainly any script that you share with others or post on the internet should use this (to avoid embarrassing yourself [as I do all the time]).
Without further ado, let me introduce you to fabulous new Set-StrictMode:
SYNOPSIS Establishes and enforces coding rules in expressions, scripts, and script blocks.
SYNTAX Set-StrictMode -Off -Version <Version> [<CommonParameters>]
DETAILED DESCRIPTION The Set-StrictMode cmdlet configures strict mode for the current scope and turns it on and off. When strict mode is on, Windows PowerShell generates a terminating error when the content of an expression, script, or script block vi olates basic best-practice coding rules. The strict mode is enforced only in the scope in which you set it.
Set-StrictMode has three settings.
Version 1: Prohibits references to uninitialized variables (unless the variables are in strings).
Version 2: Prohibits references to uninitialized variables (including variables in strings). Prohibits references to non-existent properties of an object. Prohibits invalid function syntax (parentheses and commas).
Latest: Selects the latest (most strict) version setting.
When Set-StrictMode is off, uninitialized variables (Version 1) are assumed to have a value of 0 or $null, dependin g on type. References to non-existent properties return $null. and the results of invalid function syntax vary with the error.
Wider and wider the dynamic range of PowerShell grows!
Jeffrey Snover [MSFT]Windows Management Partner ArchitectVisit the Windows PowerShell Team blog at: http://blogs.msdn.com/PowerShellVisit the Windows PowerShell ScriptCenter at: http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx
PingBack from http://HuddledMasses.org/wpf-from-powershell-select-grid/
I really like the increased functionality however I'm curious why you didn't go with something like #require strict -v 2. Was it primarily to support the global/shell scope i.e. interactive usage?
This is a really exciting feature. I think the relaxed semantics of PowerShell are very powerful for most scripting. But for my larger script sets/programs I need a bit more checking and this will help out tremendously.
A great addition. Very similar to Perl's "use strict". I feel that you guys are certainly picking the better elements of many different languages.
If I run the following powershell code:
Set-StrictMode -Version Latest
mkdir "...path here..."
and the path supplied to mkdir does not exist, the mkdir cmdlet will crash with error:
The variable '$_' cannot be retrieved because it has not been set. At line 50, char 38.
if you need more information about my previous post regarding mkdir crash at line 50, contact me at email@example.com.
Ben: An example would be great. Can you post the issue on http://connect.microsoft.com/PowerShell so that we can track it? Thanks.
Lee Holmes [MSFT]
Windows PowerShell Development
Sorry, I just realized I'd posted this a while back, but cannot duplicate the problem anymore. You can remove it from the page if you want.