PowerShell Good Practices

In this article I would discuss about some of the good practices that we should follow in PowerShell scripting. I have been working a lot in last couple of months in PowerShell so I would be sharing the good practices which helped me overcome the real life problems.

Parameters in PowerShell

Parameters in PowerShell have a very special role. In PowerShell, we can specify parameters to a function as well as to a script file. While specifying parameters we can set some attributes to it which defines the parameter’s behavior. I would be discussing the parameter with script file. Parameters in Functions is same as with the script file.

Parameters for a Script file

We can specify parameters to a scripting file which are basically the inputs to a script file. These parameters can have an alias i.e. an alternative short name or a very well-known name which one needs to specify. For example, suppose we want to create a script that accepts “Identity” as an input and we want that user can also give input as “ID“, so we can specify that as well.

Let’s discuss first how we create parameters in PowerShell. In order to create parameters we need to create a param block at the top of the script which defines the parameters.

Following is the example of how to create a simple script which accepts parameter named Identity.

<#--- Script Begins ---#>
param(
$Identity
)
<#--- Script Ends   ---#>

Now let’s define what type of values we can pass to this script as parameter. For the simplicity in this example let’s consider Identity is of type string.

<#--- Script Begins ---#>
param
(
[string] $Identity #Identity of type String
)
<#--- Script Ends   ---#>

Note: In PowerShell Comments begins with #

Now let’s try to use newly created parameter in our script:

<#--- Script Begins ---#>
param
(
[string] $Identity #Identity of type String
)
#Main script begins here
echo $Identity
<#--- Script Ends   ---#>

In the above example, we have just created the parameter to the script file of type string and just printed it on screen. We can also pass multiple parameters to the script by defining them comma separated as in the following example.

<#--- Script Begins ---#>
param
(
[string] $Identity, #Identity of type String
[string] $FileName  #Name of the file
)
#Main script begins here
echo "Identity: $Identity, FileName: $FileName"
<#--- Script Ends   ---#>
Example of calling the script:
.\GoodPractices.ps1 "ID1" "FileName.csv"
Output:
Identity: ID1, FileName: FileName.csv

As we can notice in the above example, the first parameter is Identity and the other parameter is Filename. We have an alternate way to call the script:

Better example of calling the script:
.\GoodPractices.ps1 –FileName "FileName.csv" –Identity "ID1"
Output:
Identity: ID1, FileName: FileName.csv

As we can see that we have specified the parameters rather than just passing the parameters serially. This is also known as calling by named parameters. This approach is useful when we have a lot of parameters and we just need to specify only few parameters with rest of the parameters with their default values. In the following example, we would specify the default values to the parameters.

<#--- Script Begins ---#>
param
(
[string] $Identity, #Identity of type String
[string] $FileName="DefaultFile.csv"  #Name of the file with default value
)
#Main script begins here
echo "Identity: $Identity, FileName: $FileName"
<#--- Script Ends   ---#>
Example of calling the script:
.\GoodPractices.ps1 –Identity "ID1"
Output:
Identity: ID1, FileName: DefaultFile.csv

Now, let’s see what all we can do with the attributes for the parameters. Following are the few things which we can do by defining attribute values for a parameter.

  1. Alias Name.
  2. Mark the position of the attributes.
  3. Make a parameter mandatory.
  4. Help message for a parameter.
  5. Value from Pipeline (Advanced usage, not in scope for this article) – It is basically used to define whether it would accept values from pipeline and pass to a particular parameter.

Now let’s see how to set the alias name for a parameter.

<#--- Script Begins ---#>
param
(
[Alias("ID")]
[string] $Identity, #Identity of type String
[string] $FileName="DefaultFile.csv"  #Name of the file with default value
)
#Main script begins here
echo "Identity: $Identity, FileName: $FileName"
<#--- Script Ends   ---#>
Example of calling the script:
.\GoodPractices.ps1 –ID "ID1"
Output:
Identity: ID1, FileName: DefaultFile.csv

As we can see in the above example, we can set the alias for a particular parameter and use it for calling the script instead of using the full parameter name. Now, we would use the Parameter attribute to define the position of the parameter, make it mandatory and also define the help message for it.

<#--- Script Begins ---#>
param
(
[Alias("ID")]
[Parameter(Mandatory=$true, Position=1, HelpMessage="Identity for the script.")]
[string] $Identity, #Identity of type String
[Parameter(Mandatory=$false, Position=0, HelpMessage="Filename for the output.")]
[string] $FileName="DefaultFile.csv"  #Name of the file with default value
)
#Main script begins here
echo "Identity: $Identity, FileName: $FileName"
<#--- Script Ends   ---#>
Example of calling the script:
.\GoodPractices.ps1
Output:
cmdlet GoodPractices.ps1 at command pipeline position 1
Supply values for the following parameters:
(Type !? for Help.)
Identity: !?
Identity for the script.
Identity:

In the above example, we didn’t specify any value for Identity and we made it mandatory. So, the PowerShell would prompt for its value and would tell to type “!?” if we need any help regarding the parameter. The help message we have specified would be displayed if we type “!?
for help.

Now, let’s check what does the position attribute does. Let’s call the script in the conventional way without named parameters and see the output.

.\GoodPractices.ps1 "ID1" "FileName.csv"
Output:
Identity: FileName.csv, FileName: ID1

As we can see we changed the position of the parameters so the values are sent to the parameters according to their position. Similarly, we can provide parameters to function and also provide the help message and positioning in the same way as we did with parameters in Script file.

So as a good practice we should provide proper parameters to the script file and along with proper help messages which can be understood by the person or the user of the script.

Help in PowerShell

Comments are very useful for understanding the code. But what if comments can be useful to script users along with the developers. Let’s see how this can be done in PowerShell.

PowerShell provides a very useful method or cmdlet named Get-Help which is used to get help for any other cmdlet, function or a script file in PowerShell. So, in order to make Get-Help cmdlet useful for our own scripts we have to comment them in a pre-defined way to make most out of it.

Following is the example of a script file which has proper comments which is used to generate help by using Get-Help cmdlet.

<#
.SYNOPSIS
 A brief description or synopsis of the function or script.
.DESCRIPTION
 A detailed description of the function or script.
.NOTES
 File Name : GoodPractices.ps1
 Author : Nikhil Doomra
 Prerequisite : PowerShell Version 2.0 or higher.
 Copyright 2014 – My Company
.LINK
 https://nikhildoomra.wordpress.com
.PARAMETER Param1
 Parameter 1 help
.PARAMETER Param2
 Parameter 2 help
.EXAMPLE
 Sample Example 1 details
.EXAMPLE
 Sample Example 2 details
.EXAMPLE
 Sample Example 3 details
#>

For more information on comments. Please refer TechNet article.

Make the artifacts globally available

When we create scripts which contains common useful methods and we want those methods to be accessible after the script is executed then we use the keyword global. For making the methods/variables to be globally accessible add global keyword before method or a variable.

Following is the example of making a method and its variables global.

$global:GREETING = "Hello"
Function global:GreetPeople([string]$Name)
{
  echo "$GREETING $Name"
}

The above example creates a method named GreetPeople which is globally accessible along with a variable named GREETING.

Note: If we create the global method then all the external variables that are being used should be global otherwise the method would not work as expected outside the script file.

Some Useful Cmdlets

Following are the some useful cmdlets that can be used along which are very useful:

  1. Measure-Command

    This cmdlet is very useful in determining the time taken by the command.

    Following is the example of running Measure-Command

    Measure-Command { echo “Hello World” }

    Note: This cmdlet executes the command but it doesn’t generate output for echo.

  2. Import-CSV

    This cmdlet is very useful in reading the csv file and doing bulk operations. For more information please refer TechNet article.

  3. Export-CSV

    This cmdlet helps in exporting the object or collection of objects as CSV. For more information please refer TechNet article.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s