Use PowerShell to Make Mandatory Parameters

ScriptingGuy1

Summary: Learn how to use Windows PowerShell to create mandatory parameters.

Weekend Scripter

Microsoft Scripting Guy, Ed Wilson, is here. I will admit that yesterday I talked about the easiest default to handle—the case of defaulting to the local computer. Not everything is so easy, nor is everything so cut-and-dry. For example, consider a function that returns users from Active Directory…In a very small environment it may be perfectly fine to return all of the users from the forest by default. In a company the size of Microsoft, such an approach would not be appreciated.

In other cases, performance is not the issue; but rather, the wide range of potential input values makes having a default value useless. For whatever reason, if a default value cannot be assigned, the solution is to make the default parameter mandatory.

In Windows PowerShell 1.0, it was common to use the throw keyword to make a parameter mandatory. I personally do not like this approach because the throw keyword raises an error, and a missing parameter is not really an error. Be that as it may, here is an example of using throw to make a parameter mandatory.

In the function, there are two parameters. The first parameter is the drive letter to query, and the second parameter is the ComputerName to which to connect. The ComputerName parameter uses the $env:computername environmental variable that was discussed in yesterday’s Weekend Scripter blog.

The if statement is used to determine if the $drive variable exists. If the variable exists, it means that it was supplied when the Get-DiskInformation function was called. If the variable does not exist, the throw statement is used to raise an error. Throw generates a terminating error; and therefore, it halts script execution. The Get-WmiObject command is never called if the $drive variable is missing. The complete Get-DiskInformation function is shown here:

Get-DiskInformation function – uses throw

Function Get-DiskInformation

{

 Param(

   [string]$drive,

   [string]$computerName = $env:computerName

) #end param

if(-not($drive)) { Throw “You must supply a value for -drive” }

 Get-WmiObject -class Win32_volume -computername $computername -filter “DriveLetter = ‘$drive'”

} #end function Get-DiskInformation

When the previous function is called without passing a value for the Disk parameter, the error message shown here is generated:

Image of error message

Because I do not like raising an error for a missing parameter, I used to check for the missing variable, display a friendly message, and exit the script rather than using throw. It was the same thing, but I was able to display more complete information. During the 2011 Scripting Games, I saw several scripts that used throw to make a parameter “mandatory.”

In Windows PowerShell 2.0, a new parameter attribute is introduced. This parameter attribute uses the Parameter keyword, and sets the Mandatory attribute to $true. The syntax to define a particular parameter as mandatory is shown here:

[Parameter(Mandatory=$true)]

A revision to the Get-DiskInformation function so that it uses the new Mandatory parameter attribute allows us to remove the if…throw construction as shown here:

if(-not($drive)) { Throw “You must supply a value for -drive” }

In addition to removing the if…throw construction, the only other change involves adding [Parameter(Mandatory=$true)] to the line immediately above the [string]$drive line. The revised Get-DiskInformation function is shown here:

Function Get-DiskInformation

{

 Param(

   [Parameter(Mandatory=$true)]

   [string]$drive,

   [string]$computerName = $env:computerName

) #end param

 Get-WmiObject -class Win32_volume -computername $computername -filter “DriveLetter = ‘$drive'”

} #end function Get-DiskInformation

When the Get-DiskInformation function is called, and no value for the Drive parameter is supplied, a pop-up dialog box appears when the function is run in the Windows PowerShell ISE. If the function runs inside the Windows PowerShell console, a prompt similar to the one produced by the Read-Host cmdlet appears. The prompt is shown in the following image.

Image of prompt

The good thing about this prompt, as opposed to one created via Read-Host, is that if you click Cancel, the script gracefully exits. If you click OK, but you have not supplied a value, an error will be generated and the script exits. Therefore, you at least have a chance of exiting the script in a graceful manner (via Cancel).

In the case of gathering disk information, there are two reasonable default values that should be investigated. The first is to hard code the value C: as a default. This is as simple as removing the Mandatory parameter attribute and assigning the value C: to the $drive variable. This is shown here:

Function Get-DiskInformation

{

 Param(

   [string]$drive = “C:”,

   [string]$computerName = $env:computerName

) #end param

 Get-WmiObject -class Win32_volume -computername $computername -filter “DriveLetter = ‘$drive'”

} #end function Get-DiskInformation

This approach works well. It allows you to run the function without any parameters, or to specify a different drive letter to query. However, if the system does not have a drive C, no information displays. While it is true that C: is a fairly safe bet, it is not guaranteed to exist on all systems everywhere.

A better approach, is to use the same technique that is used for the computer system name, that is, use an environmental variable. The SystemDrive environmental variable points to the drive letter where the operating system installs. This is a safer option than randomly choosing drive C. This approach is shown here:

Function Get-DiskInformation

{

 Param(

   [string]$drive = $env:SystemDrive,

   [string]$computerName = $env:computerName

) #end param

 Get-WmiObject -class Win32_volume -computername $computername -filter “DriveLetter = ‘$drive'”

} #end function Get-DiskInformation

When the previous function is loaded and is called with no parameters, the output shown in the following image appears.

Image of command output

This about wraps another week in the Scripting Center. Join me tomorrow as I look at using Windows PowerShell to troubleshoot Microsoft Outlook load issues.

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