{"id":9011,"date":"2012-06-18T00:01:00","date_gmt":"2012-06-18T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2012\/06\/18\/the-top-ten-powershell-best-practices-for-it-pros\/"},"modified":"2012-06-18T00:01:00","modified_gmt":"2012-06-18T00:01:00","slug":"the-top-ten-powershell-best-practices-for-it-pros","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/the-top-ten-powershell-best-practices-for-it-pros\/","title":{"rendered":"The Top Ten PowerShell Best Practices for IT Pros"},"content":{"rendered":"<p><b>Summary<\/b>: Microsoft Scripting Guy, Ed Wilson, summarizes the Windows PowerShell Best Practices Talk from Microsoft TechEd 2012.\nMicrosoft 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.\n1. Read all of the Help. Windows PowerShell has very sophisticated Help for cmdlets and for concepts. By default, the <b>Get-Help<\/b> cmdlet does not return all of the available information. Although this works well for many situations, you must use the <b>&ndash;full<\/b> 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<\/p>\n<p style=\"padding-left: 30px\">Get-Help Get-Process &ndash;full | more\n2. 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.\n3. In a script, never rely on positional parameters. Windows PowerShell cmdlets often define position numbers for parameters. An example of this is <b>Copy-Item<\/b>, which uses <b>-path<\/b> in position 1, and <b>&ndash;destination<\/b> in position 2. This makes the cmdlets very difficult to read&mdash;and worse, it makes it difficult to understand what the cmdlet actually accomplishes. For example, with <b>Copy-Item<\/b>, both parameters use a path string, and therefore the syntax is something that must be memorized.\n4. Do not use <b>Write-Host<\/b>. One of the great features of Windows PowerShell is that it is object oriented. This means that cmdlets return objects, such as <b>Get-Process<\/b>, which returns an instance of the <b>System.Diagnostics.Process<\/b> 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 <b>Write-Host<\/b> interrupts the pipeline, and destroys the object. There are times to use <b>Write-Host<\/b>, such as producing status messages in different colors, but do not use <b>Write-Host<\/b> to simply write textual output. Instead, directly display the contents of variables, and write your strings directly.\n5. Save <b>Format* <\/b>cmdlets until the end of the command line. Similar to the previous best practice, the <b>Format*<\/b> cmdlets (such as <b>Format-Table<\/b>, <b>Format-List<\/b>, and <b>Format-Wide<\/b>) change the object (from, for example, a System.Diagnostic.Process object) to a series of <b>Format*<\/b> objects. At this point, you are done. You can do nothing else with your pipeline.\n6. Do not use <b>Return<\/b>. 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.\n7. 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.\nThe 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.<\/p>\n<p style=\"padding-left: 30px\">Get-EventLog -LogName system -InstanceId 1000 &ndash;computername RemoteServer | sort timewritten\nThe following command illustrates filtering on the right by using the <b>Where-Object<\/b>. This command returns all of the events from the system event log across the wire, and then it filters. This is much less efficient.<\/p>\n<p style=\"padding-left: 30px\">Get-EventLog -LogName system &ndash;computername remoteserver | where { $_.instanceID -eq 1000 } | sort timewritten\n8. 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.<\/p>\n<p style=\"padding-left: 30px\">Get-EventLog -LogName system -InstanceId 1000 &ndash;computername RemoteServer |<\/p>\n<p style=\"padding-left: 30px\">Sort-Object timewritten\n9. Use <b>&ndash;whatif<\/b>. The <b>&ndash;whatif<\/b> 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.<\/p>\n<p style=\"padding-left: 30px\">Get-Process | stop-process -whatif\n10. Steal from the best, write the rest. Many scripts have already been written for Windows PowerShell. <a href=\"http:\/\/gallery.technet.microsoft.com\/ScriptCenter\/\" target=\"_blank\">The Scripting Guys Script Repository<\/a> 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.\nI invite you to follow me on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\">Facebook<\/a>. If you have any questions, send email to me at <a href=\"http:\/\/blogs.technet.commailto:scripter@microsoft.com\" target=\"_blank\">scripter@microsoft.com<\/a>, or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.\n<b>Ed Wilson, Microsoft Scripting Guy<\/b>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[331,3,4,348,45],"class_list":["post-9011","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-best-practices","tag-scripting-guy","tag-scripting-techniques","tag-teched2012","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>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 [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/9011","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=9011"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/9011\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=9011"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=9011"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=9011"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}