Share via


More PowerShell: A change you should make for V2. (#1)

There will be a couple more posts on changes for V2, of PowerShell but I want to get something really clear up front.

All V1 PowerShell should work in V2. Should meaning unless you have been really stupid or are very unlucky; you won’t NEED to change anything.

OK, now we’re clear on that here’s something you’re going to want to change if you ever write functions which change the state of the system…

In PowerShell V1 I had to explain to people that anything which produced results would have its output go to the console if it wasn’t sent anywhere else. Sometimes that meant explicitly writing something to the console so the user could see it without it getting merged into output that was used in another function. (See “This is not an an output”). With more knowledge of PowerShell people would discover the “Write-Verbose” and “Write-Debug” cmdlets, so the user could set a variable and get more or less output. This was good, but it meant setting a variable globally, and setting it back when you were done – unlike compiled cmdlets which could use common parameters like –verbose and –debug.  The other thing I’d explain for V1 was that potentially harmful things could take –confirm and –whatif switches. I regularly use this:
   dir *.jpg | ren -NewName {$_.name -replace "IMG_","DIVE"} –whatif
it renames photos, in this case from “IMG_1234” to “DIVE_1234” but because I don’t trust myself not to louse up the typing the bits I’m replacing I can run it with –whatif, and if that works, recall the line and delete –whatif to do it for real. Fantastic, but if you wrote a function you had to do it all yourself.

That changes in version 2 and it is really easy, here is a function which uses the new feature

 Function Disable-AutoPageFile

{ [CmdletBinding(SupportsShouldProcess=$True)]

   param()

   $pc=Get-WmiObject -class win32_computerSystem -Impersonation 3 -EnableAllPrivileges

   $pc.AutomaticManagedPagefile=$false

   If ($psCmdlet.shouldProcess("Local computer" , "Disable automatic page file"))
      { $pc.Put() | out-null }

} 

Easy stuff, get a Wmi object, change a property , save it back. But this turns off the Windows Page file on a server , serious stuff. So we want –whatif –confirm and so on.  The first line in the codeblock hooks the function up with the support it needs (it seems you must have a param() statement, even if it is empty when you use this) and then psCmdlet.shouldProcess does the magic so lets run the command …

 PS >  Disable-AutoPageFile -whatif

What if: Performing operation "Disable automatic page file" on Target "Local computer".
PS >  Disable-AutoPageFile -Confirm  Confirm

Are you sure you want to perform this action?

Performing operation "Disable automatic page file" on Target "Local computer".

[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"): n

 

Woo hoo ! I’m used to PowerShell saving me time, but how much has this just saved me ? No need put –Confirm or –whatif switches (and the rest) into the param() statement and no need to code for them, shouldprocess() tells the function if it should go ahead with the change to the system.  In fact the amount of time it would have taken to do this before meant I simply wouldn’t have bothered: now it’s so easy the only excuse for NOT doing it is if you need to keep working with V1. And bluntly, this is a reason to go to V2 at the first opportunity.

Jeffrey put up a post on pscmdlet some way back, you can modify the cmdletbinding line to match mine above and have a play with should process as well. You can see the text in the call to Should process got turned into the operation and target parts in the text, but here’s the summary of what it does with the different switches.

-Confirm Result returned depends on user input, Uses the message as a prompt
-WhatIf Always returns false, the message is displayed prefixed with What if:
-Verbose Always returns true,   the message is displayed in an alternate colour prefixed with VERBOSE (as with write-verbose)
<none of the above> Always returns true