Sunday, May 29, 2011

Blog Post: Use PowerShell Splatting to Simplify Parameter Sets

Summary: Microsoft Scripting Guy, Ed Wilson, illustrates step-by-step how to use Windows PowerShell splatting to simplify working with parameters.

Weekend Scripter

Microsoft Scripting Guy, Ed Wilson, is here. It is a perfectly lovely weekend, and things are finally beginning to settle back down after two weeks of travel. The SQL Rally in Orlando, Florida was awesome, as was TechEd in Atlanta, Georgia. One cannot begin to compare the two events or venues. SQL Rally was more like the Windows PowerShell Deep Dive in Las Vegas due to its smaller size. I really enjoy the small venues because it provides one with the chance to interact, to talk, and to get to know people.

TechEd, on the other hand, is a huge conference, and it has all the excitement of a huge conference. One gets to meet many people—for a short time—although, it is also possible to get to know a few people through repetitive contact and similar shared interests. In the following photo, Microsoft distinguished engineer, Jeffrey Snover, demonstrates a Windows PowerShell technique to Chris Piper at the Windows PowerShell deep dive in Las Vegas.

Photo of Jeffrey Snover and Chris Piper

Another cool thing about small conferences is that people are more relaxed. It is not very often that one gets to see a world famous PowerScripting Pod Caster such as Jonathan Waltz playing “walk the baby” with a yoyo in the middle of a hotel lobby after an extremely long day of sessions and conversation. This is shown in the following photo.

Photo of Jonathan Waltz

Anyway, while at TechEd in Atlanta, I had a discussion with someone who had participated in the 2011 Scripting Games. He was asking about the best way to write a script that might need to pass WMI credentials to a remote connection—or it might not need to pass credentials. In addition, he wants the script to work against the local computer. He said that during the 2011 Scripting Games, he noticed that he could not pass alternate credentials to a local WMI connection—the script would fail.

One way to handle this situation is to use multiple functions. This is the solution I saw over and over again during the 2011 Scripting Games. The following script, DemoRemoteLocal.ps1 is not one that was written by any specific writer, but it incorporates much of what I saw during the games. The script accepts several command-line parameters, including one for supplying a credential, and two switched parameters—one for local and one for remote. The ComputerName parameter uses the $env:computername environmental variable to run against the local computer.

The entry point to the script looks at the command-line parameters, and if the script is run with local, the script calls the Get-LocalBios function. If the script is run with the remote switch, the script calls the Get-RemoteBios function. Inside the Get-RemoteBios function, an if/else construction is used to determine whether to call the Get-WmiObject cmdlet with credentials. This is not a bad script, and I wrote several scripts similar to this back in the Windows PowerShell 1.0 days. The complete DemoRemoteLocal.ps1 script is shown here:

DemoRemoteLocal.ps1

Param(

 $credential,

 $computername = $env:COMPUTERNAME,

 [switch]$local,

 [switch]$remote

)

 

function Get-LocalBios

{

 Param ($computername)

 

  Get-WmiObject -class Win32_bios -ComputerName $computername

}

 

function Get-RemoteBios

{

 Param (

  $computername,

  $credential)

  if($credential)

  {

   Get-WmiObject -class Win32_bios -computername $computername `

      -Credential $credential

  }

  ELSE

  { Get-WmiObject -class Win32_bios -computername $computername }

}

 

# *** Entry Point to script ***

 

if($local) { Get-LocalBios -computername $computername }

if($remote) { Get-RemoteBios -computername $computername -credential $credential}

In Windows PowerShell 2.0, a feature called splatting is available. I have written several Hey, Scripting Guy! blogs that talk about splatting. Unfortunately, during the 2011 Scripting Games, very few participants used this technique. Splatting uses a hash table to pass parameters to a Windows PowerShell cmdlet or function. Here is a simple example in which the values for the Class parameter and the ComputerName parameter are supplied via splatting to the Get-WmiObject cmdlet.

demoSplatting.ps1

$inputParameters = @{

 Class = "Win32_bios"

 ComputerName = "hyperv-box"

 }

Get-WmiObject @inputParameters

The cool thing is that the $psboundparameters automatic variable, which holds all values that are passed when calling a function (but not default values) ends up being a hash table. Therefore, I can pass the @psboundparameters hash table to my Windows PowerShell cmdlet. If the function is called with the ComputerName parameter, that variable will be bound to psboundparameters if I pass credentials that will be bound as well. If I do not pass any values when calling the function, the Get-WmiObject cmdlet works against the local computer. Not only is the script much shorter, but it is also easier to read and to understand. The following code illustrates one way to call this function.

Get-Bios -computername hyperv-box -credential nwtraders\administrator

The complete Get-Bios function is shown here:

Get-Bios function

function Get-Bios

{

 Param (

  $computername,

  $credential)

 

  Get-WmiObject -class Win32_bios @psboundparameters

}

That is about all I want to talk about today. I think I am going to head back downstairs and jump into a book that I have been saving. The Scripting Wife bought me a new book about Christopher Marlowe, and I have been chomping at the bit to read it. Today seems like a good day to do that.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

ELECTRONICS FOR IMAGING ELECTRONIC DATA SYSTEMS ELECTRONIC ARTS ECLIPSYS EASTMAN KODAK CO

No comments:

Post a Comment