The Top Ten PowerShell Best Practices for IT Pros

Summary: Microsoft Scripting Guy, Ed Wilson, summarizes the Windows PowerShell Best Practices Talk from Microsoft TechEd 2012.

Microsoft Scripting Guy, Ed Wilson, is here. Wow, what an exciting week the Scripting Wife and I had last week. We began with Microsoft TechEd 2012 in Orlando, and we concluded the week with the IT Pro Camp in Jacksonville, Florida. During that 7-day period, we talked to literally thousands of people who are actively using Windows PowerShell, or are in the process of learning Windows PowerShell. I presented two talks at TechEd about Windows PowerShell Best Practices; one with Microsoft Windows PowerShell MVP, Don Jones, and one with Microsoft Windows PowerShell MVP, Jeffery Hicks. I thought that today, I would provide a summary of those two talks.

1. Read all of the Help. Windows PowerShell has very sophisticated Help for cmdlets and for concepts. By default, the Get-Help cmdlet does not return all of the available information. Although this works well for many situations, you must use the –full switched parameter to see information about which parameters accept pipelined input or wild cards, or to find information about default parameters. The following command illustrates this technique

Get-Help Get-Process –full | more

2. In a script, always use full parameter names. Whether at the Windows PowerShell console or in the Windows PowerShell ISE, you only need to use enough of the parameter to disambiguate it from other available parameters. It is a best practice to use the complete parameter name. This will proof your script in the future from possible new conflicting parameters that are introduced in new versions of Windows PowerShell.

3. In a script, never rely on positional parameters. Windows PowerShell cmdlets often define position numbers for parameters. An example of this is Copy-Item, which uses -path in position 1, and –destination in position 2. This makes the cmdlets very difficult to read—and worse, it makes it difficult to understand what the cmdlet actually accomplishes. For example, with Copy-Item, both parameters use a path string, and therefore the syntax is something that must be memorized.

4. Do not use Write-Host. One of the great features of Windows PowerShell is that it is object oriented. This means that cmdlets return objects, such as Get-Process, which returns an instance of the System.Diagnostics.Process object. The great thing about objects is that they have lots of methods and properties. In Windows PowerShell, these objects flow along the pipeline. Using Write-Host interrupts the pipeline, and destroys the object. There are times to use Write-Host, such as producing status messages in different colors, but do not use Write-Host to simply write textual output. Instead, directly display the contents of variables, and write your strings directly.

5. Save Format* cmdlets until the end of the command line. Similar to the previous best practice, the Format* cmdlets (such as Format-Table, Format-List, and Format-Wide) change the object (from, for example, a System.Diagnostic.Process object) to a series of Format* objects. At this point, you are done. You can do nothing else with your pipeline.

6. Do not use Return. Functions automatically return output to the calling process. In fact, it is best if you configure your functions so that they return objects. In this way, you enable the user to utilize your functions just like Windows PowerShell cmdlets.

7. Filter on the left. It is more efficient to filter returning data as close to the source of data as possible. For example, you do not want to return the entire contents of the system event log across the network to your work station, and then filter events for a specific event ID. Instead, you want to filter the system event log on the server, and then return the data.

The following command filters the system event log on a computer named RemoteServer for events with the event id of 1000. This illustrates filtering to the left.

Get-EventLog -LogName system -InstanceId 1000 –computername RemoteServer | sort timewritten

The following command illustrates filtering on the right by using the Where-Object. This command returns all of the events from the system event log across the wire, and then it filters. This is much less efficient.

Get-EventLog -LogName system –computername remoteserver | where { $_.instanceID -eq 1000 } | sort timewritten

8. Pipe to the right. When writing code in the Windows PowerShell ISE, you want to format the code so that it is easy to read. This means avoiding really really long lines of code. The best way to break up your lines of code into readable chunks is to break on the right-hand side. The following code illustrates this.

Get-EventLog -LogName system -InstanceId 1000 –computername RemoteServer |

Sort-Object timewritten

9. Use –whatif. The –whatif switch is a great way to see what a command will accomplish prior to actually executing the command. You should always use this switch when a command will change the system state. For example, the following command informs me that it will stop every process on my system.

Get-Process | stop-process -whatif

10. Steal from the best, write the rest. Many scripts have already been written for Windows PowerShell. The Scripting Guys Script Repository has thousands of scripts for many different topics. There is absolutely no reason to rewrite a perfectly good script that is already written. In addition, you might find a script that does nearly what you want, and all you need to do is make a few minor changes.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy