Learn about Windows PowerShell
Summary: Microsoft Windows PowerShell MVP, Sean Kearney, continues a series of guest blogs detailing building your own cmdlet.
Microsoft Scripting Guy, Ed Wilson, is here. Guest blogger and Windows PowerShell MVP, Sean Kearney, has written a series about building cmdlets. For more about Sean, see his previous guest blog posts.
Note This is Part 6 of a nine-part series about building your own Windows PowerShell cmdlet. Read the entire series as it unfolds.
If you don’t enable [CmdletBinding()], you can still extend features of your advanced function as a cmdlet. This is done by preceding a parameter name or names with the argument [parameter()].
The additional properties you can send with [parameter()] are:
Each of these properties has a purpose reflective of its name. This makes them quite easy to use and remember their purpose.
As you would have guessed, Mandatory means that this parameter absolutely must be in the pipeline. If it does not receive data, the cmdlet will prompt for the value. A good example of a mandatory parameter would be the path in Remove-Item. This cmdlet cannot function unless it knows what to remove. This would be mandatory for it to function.
If we want to make the $FolderName parameter mandatory in our cmdlet, we would modify it in the following fashion.
Position is simpler to deal with. If you would like users to run your cmdlet without keying in the parameter names, you can specify positions for certain parameters. For example, even though I can execute the following cmdlet…
GET-CHILDITEM –literalpath C:\MyFolder
…I can equally execute this cmdlet:
Why is that? Because the assigned position of the LiteralPath parameter is 1, as we can see from Get-Help.
With the position parameter, we can make it easier for users to execute cmdlets with parameters they might typically use. We can do the same thing to our current set of parameters.
By default, if you don’t define this, Windows Powershell will assign a position based on the order that you define the parameters. It is recommended as a best practice to always assign the position when defining the parameters. You’ll find things don’t break later on when you go to add additional parameters as you need changes.
You may or may not (because the design is completely in your hands) want to have a parameter accept data from the pipeline. This property is strictly a Boolean True or False setting. It specifies that a parameter can accept input from the pipeline. We can leverage this feature in our cmdlet by changing our parameters in the following manner.
This is similar to the prior parameter, but it specifies the actual property name that the parameter can accept from the pipeline. A good example to work with is Get-ChildItem. When the Get-ChildItem cmdlet is run against the file system, it returns multiple properties such as FullName, Extension, DirectoryName, and LastAccessTime amongst others as shown in the following example.
If we want to ensure that a parameter only accepts data from the pipeline when the property name is Extension, we can make this change to a parameter. We can tell the Add-LogFile cmdlet that we are building to accept the Extension property if passed through the pipeline.
When you use this parameter, it identifies that any data coming down the pipeline that is not already assigned to other parameters will be accepted by this variable.
There is nothing better for a user than being a little bit helpful. The Help message is a simple bit of text that you can provide to explain what this parameter is. In the case of the cmdlet we are building, it can be as simple as, “Folder to place log files in.” Here is a simple example of the HelpMessage put to use in our cmdlet.
HelpMessage=’Folder to Store Logfiles in’)]
HelpMessage=’TEXT to prepend all logfiles with’)]
HelpMessage=’File Extension for Logfiles’)]
If we ran our cmdlet now and did not provide any information for the Folder parameter (because it is a MandatoryParameter), we would see the Help message echoed in this fashion.
Our Folder parameter now has a simple line of text to explain its purpose if needed. As part of the features of the cmdlet, Windows Powershell allows the user to enter “!?” to pull up that simple line of Help.
An alias allows you to provide alternate names that a parameter can accept data with. The parameter name itself will not change; but in the case of AcceptValueByPropertyName, we can give a parameter multiple names to accept the data with automatically.
In the case of Folder, we could choose to use an alias of Path or Destination if that made more sense.
You can apply various attributes that allow you to indicate how values sent into the parameters should be dealt with or how they can be referred to alternate. Validation attributes are added like the other parameter attributes, and they can allow us to validate data being passed into the cmdlet or to specify what the cmdlet does not permit for certain parameters. The validation attributes that are available to us are:
Thank you, Sean. You absolutely ROCK! Guest Blogger Week will continue tomorrow when Sean will bring us Part 7.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at firstname.lastname@example.org, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy
[parameter(Mandatory=$True) misses the "]" at the end of the line ? Like [parameter(Mandatory=$True)] instead, or am I wrong about that?
Off Topic: Back in ancient history (before PowerShell) we used to call the method of defining function parameters by POSITION as using a BOA CONSTRUCTOR (as in By Order of Argument).
@AJB - cute. I wonder if it is any realation to a guy i went to school with - Charlie BOA.
the Second "]" is caught about three lines down. :)
@ajb and @jrv
GET-SNAKE "BOA Constrictor" | START-SONG :)
Although this will likely never be edited, I have to point out that DefaultParameterSetName=”Folder” does absolutely nothing, because Sean forgot to define a Parameter Set. DefaultParameterSetName has nothing to do with Parameter variable names.http://msdn.microsoft.com/en-us/library/dd878348(v=vs.85).aspxAlso, is it best practice to set the Position parameter variable to 0? Doesn't Sean point out an example of another cmdlet that starts at one? Microsoft does point out that the position numbers don't need to be contiguous and can also start at 0, this appears to be confirmed by the fact that the shell output translates Position 0 into Position 1. It is technically correct, so we can let that slide.On top of that, your code changes with no explanation (assuming it to be an honest mistake), because the Position parameter variables change from 0,1,2 the first go-around to 0,1,1 for the rest of the article. Again, seems like an honest mistake.Also, (sorry to keep doing this) the statement "By default, if you don’t define this, Windows Powershell will assign a position based on the order that you define the parameters" appears to be contradicted by Microsoft Documentation, which states: "When the Position keyword is not specified, the cmdlet parameter must be referenced by its name." This is also mirrored in other articles I've read.http://msdn.microsoft.com/en-us/library/ms714348(v=vs.85).aspxhttp://technet.microsoft.com/en-us/magazine/jj554301.aspxOther than that, I still learned a lot. I tend to learn a lot from the mistakes others and myself make.