다음을 통해 공유


PowerShell: Advanced Function Parameter Attributes

Link to Parent: PowerShell - Deep Dive and Best Practice

Reference for dealing with parameter attributes

What  are parameter attributes

Parameter attributes allow you to control the features/function of a parameter such as making a specific parameter mandatory.

Reference:
MSDN - Cmdlet Parameters

Cmdlet Binding Attributes

Cmdlet Binding Attributes allow you to control the features/function of how the cmdlet itself works. For example specifying the url for external help on the cmdlet or settings its impact, which controls prompting the users.

ConfirmImpact

The ConfirmImpact attribute is used to set the importance of what a cmdlet can do, typically based around its ability to destroy data.

Example:

References:
MSDN - ConfirmImpact ENUM

DefaultParameterSetName

If your script makes use of multiple ParameterSet, you can use the DefaultParameterSetName property to define which set of parameters to use by default, if the user's input does not expressly define one of the available sets.  You can also specify "None" as a value

Example:

For this Script block below there are two Parameter Sets, ByUserName and ByUserID.  The action of these sets is that if a user provides a -Name field, PowerShell will know to prompt for the mandatory $Email property as well.  However, if the user provides a value for -Id, then PowerShell will not prompt for the other values of the Parameter Set.  If the user provides no parameters at all, PowerShell will default to the ByUserName parameter set, and prompt for both mandatory values.

function Get-SomeValue{ 
[CmdletBinding(DefaultParameterSetName="ByUserName")] 
param ( 
[parameter(Position=0,
   Mandatory=$true,
   ParameterSetName="ByUserName")]
   [string]$name,
    
   [parameter(Position=1,
   Mandatory=$true,
   ParameterSetName="ByUserName")]
   [string]$Email,
 
   [parameter(Position=0,
   ParameterSetName="ByUserId",
   ValueFromPipeline=$true, 
   ValueFromPipelineByPropertyName=$true)]
   [ValidateNotNullOrEmpty()]
   [int]$id  
) 
 
    switch ($psCmdlet.ParameterSetName) {
         "ByUserName"  {#Actions to process for ByUserName
                }
         "ByUserId"  {#Actions to process for ByUserName
                }
  
        }
     
 
} 

References:
ParameterSetName
MSDN - DefaultParameterSetName Metadata
MSDN - Cmdlet Parameter Sets
MSDN PowerShell Blog - ParameterSets

HelpURI

Simply an external help reference.

Example:

References:
MSDN - Writing Help for Windows PowerShell

SupportsPaging

text

SupportsShouldProcess

You can use the SupportsShouldProcess Cmdlet binding to instruct PowerShell's underlying engine to allow for the -WhatIf Parameter.  In the following Function, you will see both how to instruct PowerShell to Support Should Process, and also how to use it within your functions.

Function Set-Something{
[CmdletBinding(SupportsShouldProcess=$true)]
 Param(
    [Parameter(Mandatory=$false,Position=0,HelpMessage="Please specify the users to be Set")]
            [string[]]$User,[string]$SomeProperty
             
            )
     
    #You use the syntax on the following line to determine whether or not -WhatIf was specified
    #The syntax is as follows for the Generated -WhatIf message: 
    #$PSCmdlet.ShouldProcess(Target,Operation)
    #What if: Performing the operation "Operation" on target "Target".
    if($PSCmdlet.ShouldProcess($User,"Set Property to '$SomeProperty'")){
        Write-output ("Preparing to Set-Something: $SomeProperty on $User")
                                 
    }
 
}

PositionalBinding

text

Parameter Attribute

These are used to modify how individual parameters are managed. They are applied in the following form:

Param(
    [parameter(attribute=value, attribute=value)]
    [string]
    $variable
)

 

Mandatory

This is used to make a parameter required. It takes a true or false value. The default is false so typically this is only applied if you want to make a parameter required.

Param(
    [parameter(Mandatory=$true)]
    [string]
    $variable
)

 

Position

If a function is called with parameters and the parameter isn't assigned by name, its done by position, and the Position parameter attributes value indicates which value is assigned to which parameter. This is 0 based assignment.

Function Get-NameAndAge {
Param(
    [parameter(Position=0)]
    [string]
    $Name,
    [parameter(Position=1)]
    [int]
    $age
 
)
write-host "Name: $name Age: $age"
}
 
#can be called the normal way,
Get-NameAndAge -Name Justin -age 30
 
#or, because we've defined position values we can call it without named parameters
Get-NameAndAge Justin 30

ParameterSetName

This is used to define different combinations of parameters. For example if you have a function that can take a username, or a computername and action, you could say that if you provide a computername then the user can not also provide a username.

function Invoke-OnElement {
param(
    [parameter(parametersetname="byname")]
    $username,
    [parameter(parametersetname="bycomputer")]
    $computername,
    $description
)
 
switch($PsCmdlet.ParameterSetName)
{
    "byname" { Set-NameProperty -user $username -description $description}
    "bycomputer" { Set-ComputerProperty -computer $computername -description $description}
}
 
}

 

ValueFromPipeline

This is used to accept data from the pipeline. This part can actually get a little tricky in how you design your function. There are two uses cases for something like this, one being passing values over the pipe or using them directly.

"serverA","serverB" | Test-Server
or
Test-Server -ComputerName "serverA","serverB"

In order to have both of these work you'll need to define your function in this way.

function Test-Server {
param(
    [parameter(ValueFromPipe=$true)]
    [string[]]
    $computername
)
 
PROCESS
{
    foreach($system in  $computername)
    {
        #run tests
    }
}
}

In order for the function to handle the items from the pipe, you need to use the begin/process/end blocks (only process shown above) but in order for it to handle an array passed in to the param you need the foreach loop. This doesn't make for the prettiest function but this is the setup for it.

ValueFromPipelineByPropertyName

text

ValueFromRemainingArgument

text

HelpMessage

text

Alias

As a cmdlet or function changes over time, you may want to change the name for a parameter for better self-documentation or consistency with another set of functions or cmdlets. However, this may carry the risk of breaking existing callers.

The Alias parameter attribute allows you to accept different names for the same input.  The function below may have taken only MachineName before. It will now accept either ComputerName or MachineName as its primary parameter, and ComputerName will be shown as the preferred name.

Function Get-SomeValue {
[CmdletBinding()]
param(
     [parameter(Mandatory=$True,ValueFromPipeline=$True,position=0)]
     [Alias("MachineName")]
     [string[]]$ComputerName)
       
      Get-WmiObject -Class Win32_ComputerSystem -ComputerName $ComputerName
 
}

Parameter Validation Attributes

All validation attributes are in the same general form  [type(condition)] so the following sections will only contain the name/format for these.
For more details read the About_Functions_Advanced_Parameters
Here is a basic example

AllowNull

Allows $null value
[AllowNull()]

AllowEmptyString

Allows "" values
[AllowEmptyString()]

AllowEmptyCollection

Allows @() as a value
[AllowEmptyCollection()]

ValidateCount

Checks number of items in a collection
[ValidateCount(1,5)]

ValidateLength

Checks the length of the value passed in
[ValidateLength(1,10)]

ValidatePattern

Checks the value against a Regular Expression (regex)
[ValidatePattern("[0-9][0-9][0-9][0-9]")]

ValidateRange

Checks to make sure the number provided is within a range. You'll want to make sure the type for the parameter is a valid number type
[ValidateRange(1,10)]

ValidateScript

Uses PS syntax to validate a value. The $_ is used to represent the parameter value
[ValidateScript( { $_ -ge (get-date) } ) ]

ValidateSet

Makes sure the value is in the provided set. This also provides intellisense for the cmdlet

[ValidateSet("Low","Medium","High")]

ValidateNotNull

Makes sure the value is anything but null
[ValidateNotNull()]

ValidateNotNullOrEmpty

Makes sure the value is not null or and empty string ""
[ValidateNotNullOrEmpty()]

Dynamic Parameters

text

Switch Parameters

You can specify the name of a Switch parameter if you would like to allow the user to be able to run an operation if the switch is provided.  

For instance, consider the below snippet, which would move users from one Active Directory OU to another, and you wanted to provide your end-user the option to display a certain attribute when running, you could create a [Switch] Parameter named 'ListOU'.  

Function Move-Users {
[CmdletBinding(SupportsShouldProcess=$true)]
 Param(
    [Parameter(Mandatory=$false,Position=0,HelpMessage="Please specify the users to be moved to the appropriate OUs.  This can be either names within a file, or a hashtable.")]
            [string[]]$DestinationOU = 'corp.dc/destination/ou',
            [string[]]$UserList,
            [switch]$ListOUs
            )
   $Users = Import-Csv $UserList
   ForEach ($User in  $Users){
   $UserObj = Get-ADUser $Users.Name
     If ($ListOUs) { "User Moving from $($UserObj.Fullname) to $DestinationOu"}
     #Code Continues...
     }
}

If the command is executed without the switch Provided, this value will return as $False, and the code block which displays the message will not be displayed.  However, if they do provide the -ListOU switch, $ListOU will have a value of $True and then the code-block will be executed, displaying the special message.

References

 

PowerShell Help

See Also

 

Other Languages