Learn about Windows PowerShell
Microsoft Scripting Guy Ed Wilson here. One of the cool things about writing scripts on the weekend, is the lack of distraction. Because there are few things to compete for one’s attention, there is more time to polish and more time to clean up the code.
For example, consider the ConversionModule.psm1 module I worked on yesterday. After I finished writing it and posted it to the SharePoint site that Craig and I share, I stretched out on the futon in my entertainment room, put on A Midsummer Night’s Dream by Mendelssohn, and sipped a cup of Rooibos tea. I turned on an electric blanket and in my relaxed state thought of several things; I could do to improve the module. Ah, the beauties of weekend scripting. During the rapid pace of the normal workday, I never find time to stretch out on a futon and listen to Mendelssohn.
So what is wrong with the module I wrote yesterday? Not a thing that I know of. It works. Nevertheless, there are a few things to do to improve the function. As seen in the following image some of the information that is returned by the Get-Help cmdlet is incomplete (for example, the Description) and some of the information (such as the data type of the input parameter) is ambiguous.
The Description is the easiest problem to fix. To fix this, you need only supply a string value for the .DESCRIPTION tag inside the help area. It is a best practice to use a complete sentence for the description. In addition, I like to include the name of the function in the description because the Synopsis does not generally repeat the function name. The modification is seen in the following image.
After the change has been made, save the module and use the Copy-Module.ps1 script to install the module. And after the module has been installed, import it and use the Get-Help cmdlet to see the results. As seen in the following image, the change was successful.
We now need to add the Description tag to each of the other functions. I use copy and paste to copy the original description from the first function and paste it in each of the other functions. After I have completed the copy-and-paste operations, I go back and edit each one in succession.
The next problem that needs to be addressed is the ambiguous data type that is reported for the input parameters. As seen in the following image the feet parameter is reported as an <Object>, which though true is less than illuminating because everything in Windows PowerShell is an object. Data types that are commonly used are integers and strings are represented as [int] and [string], respectively. An integer is a whole number, and when making value conversions from Fahrenheit to Celsius, it is important to be able to use decimal places. What is that data type called? You could open Internet Explorer, navigate over to MSDN, and spend the next 30 minutes or so Binging around trying to arrive at the correct data type. Or you can use the GetType method as seen here and quickly arrive at the System.Double data type:
PS C:\> $a = 1.1111PS C:\> $a.GetType()IsPublic IsSerial Name BaseType-------- -------- ---- --------True True Double System.ValueTypePS C:\>
To use Double as a type constraint, you merely place it inside a set of square brackets inside the parameter declaration. This is seen here:
param( [Parameter(Mandatory = $true,Position = 0,valueFromPipeline=$true)] [Double] $feet) #end param
Once again, a copy-and-paste operation is in order to fix the remaining parameter statements. The resulting Get-Help output is seen in the following image.
In the full view of help, you can obtain more information about the input types and output types of the script. The .Inputs and the .Outputs tags as shown here control these values.
.Inputs [double] .Outputs [string]
After the tags have been added to all the functions, and the modified module is installed and imported, you can use Get-Help as seen in the following image.
The modified ConversionModuleV2.psm1 module is seen here.
ConversionModuleV2.psm1
Function ConvertTo-Meters{ <# .Synopsis Converts feet into meters .Description The ConvertTo-Meters function accepts a value in feet and returns a string indicating the number of meters. .Example ConvertTo-Meters 1 Converts 1 foot into meters .Parameter feet The number of feet to be converted .Inputs [double] .Outputs [string] .Notes NAME: ConvertTo-Meters AUTHOR: Ed Wilson LASTEDIT: 1/31/2010 KEYWORDS: WeekEnd Scripter, Modules, Getting Started .Link Http://www.ScriptingGuys.com #Requires -Version 2.0 #> [CmdletBinding()] param( [Parameter(Mandatory = $true,Position = 0,valueFromPipeline=$true)] [Double] $feet) #end param "$feet feet equals $($feet*.31) meters"} #end ConvertTo-MetersFunction ConvertTo-Feet{ <# .Synopsis Converts meters into feet .Description The ConvertTo-Feet function accepts a value in meters and returns a string indicating the number of feet. .Example ConvertTo-Feet 1 Converts 1 meter into feet .Parameter meters The number of meters to be converted into feet .Inputs [double] .Outputs [string] .Notes NAME: ConvertTo-Feet AUTHOR: Ed Wilson LASTEDIT: 1/31/2010 KEYWORDS: WeekEnd Scripter, Modules, Getting Started .Link Http://www.ScriptingGuys.com #Requires -Version 2.0 #> [CmdletBinding()] param( [Parameter(Mandatory = $true,Position = 0,valueFromPipeline=$true)] [Double] $meters) #end param "$meters meters equals $($meters * 3.28) feet"} #end ConvertTo-FeetFunction ConvertTo-Fahrenheit{ <# .Synopsis Converts celsius into fahrenheit .Description The ConvertTo-Fahrenheit function accepts a value in celsius and returns a string indicating the temperature in Fahrenheit. .Example ConvertTo-Fahrenheit 1 Converts 1 degree celsius into fahrenheit .Parameter celsius The temperature to be converted into fahrenheit .Inputs [double] .Outputs [string] .Notes NAME: ConvertTo-Fahrenheit AUTHOR: Ed Wilson LASTEDIT: 1/31/2010 KEYWORDS: WeekEnd Scripter, Modules, Getting Started .Link Http://www.ScriptingGuys.com #Requires -Version 2.0 #> [CmdletBinding()] param( [Parameter(Mandatory = $true,Position = 0,valueFromPipeline=$true)] [Double] $celsius) #end param "$celsius celsius equals $((1.8 * $celsius) + 32 ) fahrenheit"} #end ConvertTo-FahrenheitFunction ConvertTo-celsius{ <# .Synopsis Converts fahrenheit into celsius .Description The ConvertTo-Celsius function accepts a value in fahrenheit and returns a string indicating the temperature in celsius. .Example ConvertTo-Celsius 1 Converts 1 degree fahrenheit into celsius .Parameter fahrenheit The temperature to be converted .Inputs [double] .Outputs [string] .Notes NAME: ConvertTo-Celsius AUTHOR: Ed Wilson LASTEDIT: 1/31/2010 KEYWORDS: WeekEnd Scripter, Modules, Getting Started .Link Http://www.ScriptingGuys.com #Requires -Version 2.0 #> [CmdletBinding()] param( [Parameter(Mandatory = $true,Position = 0,valueFromPipeline=$true)] [Double] $fahrenheit) #end param "$fahrenheit fahrenheit equals $( (($fahrenheit - 32)/9)*5 ) celsius"} #end ConvertT-ocelsiusFunction ConvertTo-Miles{ <# .Synopsis Converts kilometers into miles .Description The ConvertTo-Miles function accepts a value in kilometers and returns a string indicating the distance in miles. .Example ConvertTo-Miles Converts 1 kilometer into miles .Parameter kilometer The distance to be converted .Inputs [double] .Outputs [string] .Notes NAME: ConvertTo-Miles AUTHOR: Ed Wilson LASTEDIT: 1/31/2010 KEYWORDS: WeekEnd Scripter, Modules, Getting Started .Link Http://www.ScriptingGuys.com #Requires -Version 2.0 #> [CmdletBinding()] param( [Parameter(Mandatory = $true,Position = 0,valueFromPipeline=$true)] [Double] $kilometer) #end param "$kilometer kilometers equals $( ($kilometer *.6211) ) miles"} #end convertToMilesFunction ConvertTo-Kilometers{ <# .Synopsis Converts miles into Kilometers .Description The ConvertTo-Kilometers function accepts a value in miles and returns a string indicating the distance in kilometers. .Example ConvertTo-Kilometers 1 Converts 1 mile into kilometers .Parameter miles The distance to be converted .Inputs [double] .Outputs [string] .Notes NAME: ConvertTo-Kilometers AUTHOR: Ed Wilson LASTEDIT: 1/31/2010 KEYWORDS: WeekEnd Scripter, Modules, Getting Started .Link Http://www.ScriptingGuys.com #Requires -Version 2.0 #> [CmdletBinding()] param( [Parameter(Mandatory = $true,Position = 0,valueFromPipeline=$true)] [Double] $miles) #end param "$miles miles equals $( ($miles * 1.61) ) kilometers"} #end convertTo-Kilometers
If you want to know exactly what we will be covering in the coming week, follow us on Twitter and Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson and Craig Liebendorfer, Scripting Guys
How to use .INPUTS tag if you have several input parameters and these parameters are not the same types?
The .Inputs tag is used to tell PowerShell the data type of input that is passed via the pipeline. If your function does not accept data via the pipeline, then you would not need the .inputs tag.
Hi Scripting Guy,
Just starting with modules and following your examples; please note that us metric Europeans spell it metres!