<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://powershell.com/cs/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Search results for 'app:weblogs' matching tag 'scripting techniques'</title><link>http://powershell.com/cs/search/SearchResults.aspx?q=app:weblogs&amp;tag=scripting+techniques&amp;orTags=0&amp;o=DateDescending</link><description>Search results for 'app:weblogs' matching tag 'scripting techniques'</description><dc:language>en-US</dc:language><generator>CommunityServer 2008.5 (Build: 30929.2835)</generator><item><title>I Found This Module—What Do I Do?</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2013/05/15/i-found-this-module-what-do-i-do.aspx</link><pubDate>Wed, 15 May 2013 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:23570</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;strong style="font-size:12px;"&gt;Summary&lt;/strong&gt;&lt;span style="font-size:12px;"&gt;: Microsoft Scripting Guy, Ed Wilson, talks about how to use a Windows PowerShell module.&lt;/span&gt;&lt;span style="font-size:12px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://img.microsoft.com/library/media/1033/technet/images/scriptcenter/qanda/q-sm.jpg" alt="Hey, Scripting Guy! Question" /&gt;&amp;nbsp;Hey, Scripting Guy! &amp;nbsp;I found this module in the Scripting Guys Script Repository. Now what do I do?&lt;/p&gt;
&lt;p&gt;&amp;mdash;SH&lt;/p&gt;
&lt;p&gt;&lt;img src="http://img.microsoft.com/library/media/1033/technet/images/scriptcenter/qanda/a-sm.jpg" alt="Hey, Scripting Guy! Answer" /&gt;&amp;nbsp;Hello SH,&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. This morning I have been busy booking travel to &lt;a href="http://europe.msteched.com/#fbid=Y6s0qEgGIo3" target="_blank"&gt;Madrid, Spain for TechEd 2013&lt;/a&gt;. I will have a booth there with the Scripting Wife. In addition, I will be joining the Windows PowerShell team for their instructor led lab&amp;mdash;it will be way cool. Air travel these days is so much fun, I genuinely look forward to each upcoming flight. This includes my flight to &lt;a href="http://northamerica.msteched.com/#fbid=fii1JDbUFpU" target="_blank"&gt;TechEd 2013 in New Orleans&lt;/a&gt;, where you can also find the Scripting Wife and me. (I am also conducting a Windows PowerShell instructor led lab in the &lt;a href="http://en.wikipedia.org/wiki/New_Orleans" target="_blank"&gt;big easy&lt;/a&gt;.)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;strong&gt;Note&amp;nbsp;&amp;nbsp;&lt;/strong&gt;This is the fourth part of a multipart series about using Windows PowerShell functions and modules. Prior to reading this blog, you should read the previous posts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2013/05/08/i-found-this-powershell-function-now-what-do-i-do.aspx" target="_blank"&gt;I Found this PowerShell Function&amp;mdash;Now What Do I Do? Part 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2013/05/13/i-found-this-powershell-function-now-what-do-i-do-part-2.aspx" target="_blank"&gt;I Found this PowerShell Function&amp;mdash;Now What Do I Do? Part 2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2013/05/14/i-found-this-powershell-function-now-what-do-i-do-part-3.aspx" target="_blank"&gt;I Found this PowerShell Function&amp;mdash;Now What Do I Do? Part 3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;What do I do with a module I find?&lt;/h2&gt;
&lt;p&gt;Let us suppose that I find a module such as the &lt;a href="http://gallery.technet.microsoft.com/scriptcenter/2d191bcd-3308-4edd-9de2-88dff796b0bc" target="_blank"&gt;Windows Update PowerShell Module&lt;/a&gt; in the Scripting Guys Script Repository. What do I do with it? Well, the first thing I need to do is to download and to install the module. But this is where things are actually a bit confusing. This is because I can put the module anywhere I want to put it. One of the great things about Windows PowerShell modules is that no installer is required. Most modules, in fact, use a simple copy and paste type of installation (the so-called XCOPY deployment, but you do not need to use XCOPY if you do not wish to do so).&lt;/p&gt;
&lt;h2&gt;Where do I put the module?&lt;/h2&gt;
&lt;p&gt;There are two places I can put modules so that Windows PowerShell will automatically recognize them, and will automatically import them. These locations are stored in the &lt;strong&gt;PSModulePath &lt;/strong&gt;environmental variable&lt;em&gt;. &lt;/em&gt;From a basic categorization standpoint, one is in my profile/home directory, and the other one is in System32. This output on my computer is shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PS C:\&amp;gt; $env:PSModulePath -split &amp;quot;;&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;C:\Users\ed.IAMMRED\Documents\WindowsPowerShell\Modules&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;C:\Windows\system32\WindowsPowerShell\v1.0\Modules\&lt;/p&gt;
&lt;p&gt;It requires admin rights to copy something into the System32 folder, and that is where people sometimes place modules that require admin rights. The problem with this location is that when Windows undergoes servicing, it remotes items from the system folders that it does not know about. This means that your admin&lt;em&gt; &lt;/em&gt;type of modules can easily become deleted the next time you run Windows update or apply a service pack.&lt;/p&gt;
&lt;p&gt;The problem with storing all modules in my profile/home directory location occurs if I am running as a normal user, and then I need to elevate to an account with admin rights so I can run a module that requires admin rights. My profile/home directory is now a NEW location because I am running as a different user. This makes it painful to navigate back to the old user profile location to launch the module manually.&lt;/p&gt;
&lt;p&gt;The answer is simple. Modify the &lt;strong&gt;$env:PSModulePath&lt;/strong&gt; location to include an additional folder&amp;mdash;either one on a network, or a folder in an easily accessible location. For example, I have a central data&lt;em&gt; &lt;/em&gt;folder that I use to simplify backups (an XCOPY backup, so to speak). I could easily create a central modules folder that is accessible for all users on the computer. This technique is shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PS C:\&amp;gt; $env:PSModulePath = $env:PSModulePath + &amp;#39;;c:\data\modules&amp;#39;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PS C:\&amp;gt; $env:PSModulePath -split &amp;quot;;&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;C:\Users\ed.IAMMRED\Documents\WindowsPowerShell\Modules&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;C:\Windows\system32\WindowsPowerShell\v1.0\Modules\&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;c:\data\modules&lt;/p&gt;
&lt;h2&gt;How do I put the module in its location?&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s go back to the &lt;em&gt;Windows Update PowerShell Module &lt;/em&gt;from the Scripting Guys Script Repository. It is contained in a file called PSWindowsUpdate.zip. I click the PSWindowsUpdate.zip file in the Script Repository, and after I agree to the terms of use, Internet Explorer asks if I want to Open, Save, or Cancel my action. This is shown in the image that follows.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/5736.hsg_2D00_5_2D00_15_2D00_13_2D00_01.png"&gt;&lt;img title="Image of menu" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/5736.hsg_2D00_5_2D00_15_2D00_13_2D00_01.png" alt="Image of menu" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If I select Open, the zipped file opens revealing a subfolder as shown here:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/2677.hsg_2D00_5_2D00_15_2D00_13_2D00_02.png"&gt;&lt;img title="Image of menu" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/2677.hsg_2D00_5_2D00_15_2D00_13_2D00_02.png" alt="Image of menu" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Cool, it seems that all I need to do is to open my module directory and drag the folder from the zipped folder to my module home directory. The problem if I do this is the files in the folder will all be blocked.&amp;nbsp; This is shown in the following image.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/4718.hsg_2D00_5_2D00_15_2D00_13_2D00_03.png"&gt;&lt;img title="Image of menu" src="http://blogs.technet.com/resized-image.ashx/__size/350x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/4718.hsg_2D00_5_2D00_15_2D00_13_2D00_03.png" alt="Image of menu" width="350" height="480" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I can use Windows PowerShell&amp;nbsp;3.0 to unblock the files, but it is easier to unblock the files before installation. To do this, save the .zip file, then right-click it to unblock the file prior to extraction. In this way, all the files contained therein are unblocked. However, if I forget to do this, I can use a command such as the following to unblock the files:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PS C:\Users\ed.IAMMRED\Documents\WindowsPowerShell\Modules&amp;gt; gci .\PSWindowsUpdate -Re&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;curse | Unblock-File&lt;/p&gt;
&lt;p&gt;After I copy the unzipped and unblocked Windows PowerShell module files to the module directory, I can import the module and use the cmdlets. Because I am dealing with Windows update, the Windows PowerShell console needs to be elevated. The following error appears if the Windows PowerShell console is not elevated.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0181.hsg_2D00_5_2D00_15_2D00_13_2D00_04.png"&gt;&lt;img title="Image of error message" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0181.hsg_2D00_5_2D00_15_2D00_13_2D00_04.png" alt="Image of error message" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After I elevate Windows PowerShell, I use the &lt;strong&gt;Import-Module&lt;/strong&gt; cmdlet to import the module, and I use the &lt;strong&gt;Get-Command&lt;/strong&gt; cmdlet to see what commands are exposed by the module. This is shown here.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/6014.hsg_2D00_5_2D00_15_2D00_13_2D00_05.png"&gt;&lt;img title="Image of command output" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/6014.hsg_2D00_5_2D00_15_2D00_13_2D00_05.png" alt="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now that I see the commands, I can use them just like any other Windows PowerShell command from any other module. So I can check to see what updates are available via the &lt;strong&gt;Get-WUList&lt;/strong&gt; cmdlet (function) as shown here:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PS C:\&amp;gt; Get-WUList&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;ComputerName Status KB&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;Size Title&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;------------ ------ --&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ---- -----&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;EDLT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ---H-- KB2694771&amp;nbsp;&amp;nbsp; 5 MB Bing Desktop v1.2&lt;/p&gt;
&lt;p&gt;To install an update, I use the &lt;strong&gt;Get-WUInstall&lt;/strong&gt; function, and to hide an update I use the &lt;strong&gt;Hide-WUUpdate&lt;/strong&gt; command. Pipeline support is available.&lt;/p&gt;
&lt;p&gt;I can even check to see if a reboot is required as shown here:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PS C:\&amp;gt; Get-WURebootStatus&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Reboot is not Required.&lt;/p&gt;
&lt;p&gt;SH, that is all there is to using a Windows PowerShell module.&amp;nbsp; Join me tomorrow when I will reveal the 2013 Scripting Games Event 4.&lt;/p&gt;
&lt;p&gt;I invite you to follow me on &lt;a href="http://bit.ly/scriptingguystwitter" target="_blank"&gt;Twitter&lt;/a&gt; and &lt;a href="http://bit.ly/scriptingguysfacebook" target="_blank"&gt;Facebook&lt;/a&gt;. If you have any questions, send email to me at &lt;a href="mailto:scripter@microsoft.com" target="_blank"&gt;scripter@microsoft.com&lt;/a&gt;, or post your questions on the &lt;a href="http://bit.ly/scriptingforum" target="_blank"&gt;Official Scripting Guys Forum&lt;/a&gt;. See you tomorrow. Until then, peace.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ed Wilson, Microsoft Scripting Guy&lt;/strong&gt;&lt;span style="font-size:12px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3572613" width="1" height="1" alt="" /&gt;</description></item><item><title>I Found this PowerShell Function—Now What Do I Do? Part 3</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2013/05/14/i-found-this-powershell-function-now-what-do-i-do-part-3.aspx</link><pubDate>Tue, 14 May 2013 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:23459</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;strong style="font-size:12px;"&gt;Summary&lt;/strong&gt;&lt;span style="font-size:12px;"&gt;: Microsoft Scripting Guy, Ed Wilson, talks about combining functions into a single function file, and using them in scripts.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. This morning is sort of mellow. It seems as if the clouds are touching the ground, and all sound is suppressed by a thick cloth batten. After seemingly weeks of rain, it is nice to have a not so wet day. I am on the lanai sitting in our porch swing reading my email via Outlook Web Access on my Surface RT. I love the long battery life and the portability of this device, and the fact that it has Windows PowerShell makes it even better.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;strong&gt;Note&amp;nbsp;&amp;nbsp;&lt;/strong&gt;This is the third part of a multipart series about using Windows PowerShell functions and modules. Prior to reading this blog, you should read the previous posts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2013/05/08/i-found-this-powershell-function-now-what-do-i-do.aspx" target="_blank"&gt;I Found this PowerShell Function&amp;mdash;Now What Do I Do? Part 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2013/05/13/i-found-this-powershell-function-now-what-do-i-do-part-2.aspx" target="_blank"&gt;I Found this PowerShell Function&amp;mdash;Now What Do I Do? Part 2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;em&gt;&amp;nbsp;&lt;/em&gt;If one function is cool, then two are even better&lt;/h2&gt;
&lt;p&gt;Yesterday in Part 2, I talked about dot sourcing a script that contains a function into the Windows PowerShell console so I could use the function just like it was a cmdlet. Today I want to expand on that idea just a bit by including two functions in a script file. The two functions use WMI to create a similar output to standard CIM functions in Windows&amp;nbsp;8. The equilivant functions in Windows&amp;nbsp;8 are &lt;strong&gt;Get-Volume&lt;/strong&gt; and &lt;strong&gt;Get-NetAdapter&lt;/strong&gt;. Here is the content of the two WMI functions:&lt;/p&gt;
&lt;h3 style="padding-left:30px;"&gt;TwoWmiFunctions.ps1&lt;/h3&gt;
&lt;p style="padding-left:30px;"&gt;Function Get-Volume&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;{&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;Param($cn = $env:computername)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;Get-WmiObject -class win32_volume -ComputerName $cn|&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;Select-Object driveletter, @{LABEL=&amp;#39;FileSystemLabel&amp;#39;;EXPRESSION={$_.label}},&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp; filesystem,&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp; @{LABEL=&amp;quot;Size&amp;quot;;EXPRESSION={&amp;quot;{0:N2} Gigabytes&amp;quot; -f ($_.capacity/1GB) }},&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp; @{LABEL=&amp;quot;SizeRemaining&amp;quot;;EXPRESSION={&amp;quot;{0:N2} Gigabytes&amp;quot; -f ($_.freespace/1GB) }}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;} #end function Get-Volume&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Function Get-NetAdapter&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;{&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;Param($cn = $env:computername)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp; Get-WmiObject win32_networkadapter |&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp; Where-Object {$_.netconnectionstatus} |&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Select-Object name,&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @{LABEL=&amp;#39;InterfaceDescription&amp;#39;;EXPRESSION={$_.Description}},&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @{LABEL=&amp;#39;ifIndex&amp;#39;;EXPRESSION={$_.Index}},&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @{LABEL=&amp;#39;Status&amp;#39;;EXPRESSION={&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; If($_.netconnectionstatus -eq 2){&amp;quot;not present&amp;quot;}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; If($_.netconnectionstatus -eq 4){&amp;quot;up&amp;quot;}}}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;} # end function get-NetAdapter&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:12px;"&gt;For ease of use, I have uploaded these functions to the Scripting Guys Script Repository: &lt;/span&gt;&lt;a href="http://gallery.technet.microsoft.com/scriptcenter/Two-WMI-Functions-94c31b5f" target="_blank"&gt;Two WMI Functions&lt;/a&gt;&lt;span style="font-size:12px;"&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;Using the function script by dot sourcing it&lt;/h2&gt;
&lt;p&gt;To dot source the script that contains the two functions, all I need to do is to place a period (dot) at the beginning of the console line, and then use the path to the script that contains the functions. I can then use the functions directly. This is shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;strong&gt;.&lt;/strong&gt; C:\fso\TwoWmiFunctions.ps1&lt;/p&gt;
&lt;p&gt;The following image shows dot sourcing the script that contains the two functions and then using the two functions.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0458.hsg_2D00_5_2D00_14_2D00_13_2D00_01.png"&gt;&lt;img title="Image of command output" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0458.hsg_2D00_5_2D00_14_2D00_13_2D00_01.png" alt="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Dot source to interop between Windows versions&lt;/h2&gt;
&lt;p&gt;Lots of people are migrating to Windows&amp;nbsp;8 on their desktops; but unfortunately for many network administrators, they are forced to interop between Windows&amp;nbsp;8 and other versions of Windows. One of the things that is great about Windows&amp;nbsp;8 (and Windows Server&amp;nbsp;2012 for that matter) are the many CIM functions that wrap WMI classes. These are convenient and easy to use. However, for down-level systems, I still need to use the WMI classes. To avoid really cluttering up a script with a bunch of WMI code, I can use dot sourcing to handle the transition period. Here is an example of how that might work:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;if(gcm get-volume){Get-Volume} ELSE {. C:\fso\TwoWmiFunctions.ps1; Get-Volume}&lt;/p&gt;
&lt;p&gt;So all I need to do is to use &lt;strong&gt;Get-Command&lt;/strong&gt; to see if the &lt;strong&gt;Get-Volume&lt;/strong&gt; function (available in Windows&amp;nbsp;8) exists. If it does, I call the &lt;strong&gt;Get-Volume&lt;/strong&gt; command. If the &lt;strong&gt;Get-Volume&lt;/strong&gt; function is not available (because the version of Windows is older than Windows&amp;nbsp;8), I dot source my TwoWMIFunctions.ps1 script that contains my two functions, and then I call &lt;strong&gt;Get-Volume&lt;/strong&gt; from the dot-sourced script. This makes for a nice transitional bit of code.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;strong&gt;Note&lt;/strong&gt; &amp;nbsp;When you create this sort of transitional&lt;em&gt; &lt;/em&gt;function, ensure that the property names are the same. In this way, using one function or the other will also be the same. In my example TwoWmiFunctions.ps1 script, I had to rename several WMI class property names for compatibility.&lt;/p&gt;
&lt;p&gt;In the following image, I use the dot-source technique to bring in the script that contains the compatibility functions.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/8233.hsg_2D00_5_2D00_14_2D00_13_2D00_02.png"&gt;&lt;img title="Image of command" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/8233.hsg_2D00_5_2D00_14_2D00_13_2D00_02.png" alt="Image of command" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now What Do I Do? Week will continue tomorrow when I will talk about using a Windows PowerShell module. It is really cool, and you do not want to miss it.&lt;/p&gt;
&lt;p&gt;I invite you to follow me on &lt;a href="http://bit.ly/scriptingguystwitter" target="_blank"&gt;Twitter&lt;/a&gt; and &lt;a href="http://bit.ly/scriptingguysfacebook" target="_blank"&gt;Facebook&lt;/a&gt;. If you have any questions, send email to me at &lt;a href="mailto:scripter@microsoft.com" target="_blank"&gt;scripter@microsoft.com&lt;/a&gt;, or post your questions on the &lt;a href="http://bit.ly/scriptingforum" target="_blank"&gt;Official Scripting Guys Forum&lt;/a&gt;. See you tomorrow. Until then, peace.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ed Wilson, Microsoft Scripting Guy&lt;/strong&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3572371" width="1" height="1" alt="" /&gt;</description></item><item><title>I Found this PowerShell Function—Now What Do I Do? Part 2</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2013/05/13/i-found-this-powershell-function-now-what-do-i-do-part-2.aspx</link><pubDate>Mon, 13 May 2013 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:23430</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;strong style="font-size:12px;"&gt;Summary&lt;/strong&gt;&lt;span style="font-size:12px;"&gt;: Microsoft Scripting Guy, Ed Wilson, continues his discussion about what to do with a Windows PowerShell function.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. Last week I did not get a chance to finish answering a question from JB about how to use a Windows PowerShell function.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;strong&gt;Note&lt;/strong&gt; &amp;nbsp;&amp;nbsp;This is the second part of a multipart series about using Windows PowerShell functions and modules. You should read the first blog post, &lt;a href="http://blogs.technet.com/controlpanel/blogs/posteditor.aspx?SelectedNavItem=Posts&amp;amp;WeblogID=7618&amp;amp;WeblogPostID=3570211" target="_blank"&gt;I Found this PowerShell Function&amp;mdash;Now What Do I Do? &amp;ndash; Part 1&lt;/a&gt; prior to reading this post.&lt;/p&gt;
&lt;h2&gt;Functions promote code reuse&lt;/h2&gt;
&lt;p&gt;In the first installment in this series about using functions, I talked about the more traditional technique of copying and pasting the function directly into a script. This works well if you want to write a script. But one of the powerful things about Windows PowerShell is that I do not have to write a script. In fact, the great thing about Andy Schneider&amp;rsquo;s &lt;strong&gt;Set-ScreenResolution&lt;/strong&gt; function is that he wrote it as a function.&lt;/p&gt;
&lt;h3&gt;Top ten Windows PowerShell function best practices&lt;/h3&gt;
&lt;p&gt;Of course, being able to reuse the code depends on a well written function. Here is my top ten list of Windows PowerShell function best practices.&lt;/p&gt;
&lt;p&gt;A function should:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use the standard Verb-Noun naming convention.&lt;/li&gt;
&lt;li&gt;Do one thing and do it well.&lt;/li&gt;
&lt;li&gt;Return an object.&lt;/li&gt;
&lt;li&gt;Incorporate comment-based Help.&lt;/li&gt;
&lt;li&gt;Expose parameters instead of using hard-coded values.&lt;/li&gt;
&lt;li&gt;Accept piped input if it makes sense for the use-case scenario.&lt;/li&gt;
&lt;li&gt;Run and return default information if it makes sense for the use-case scenario (instead of requiring input, or returning an error when it is run without parameters).&lt;/li&gt;
&lt;li&gt;Offer parameter aliases for common parameters (for example, CN for &lt;strong&gt;ComputerName&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;Name parameters in accordance with standard Windows PowerShell cmdlets (for example &lt;strong&gt;ComputerName&lt;/strong&gt; instead of &lt;em&gt;server, laptop, &lt;/em&gt;or &lt;em&gt;machine&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;Use parameter validation techniques to limit user input.&lt;/li&gt;
&lt;/ol&gt;
&lt;p style="padding-left:30px;"&gt;&lt;strong&gt;Note&lt;/strong&gt; &amp;nbsp;&amp;nbsp;For more information about Windows PowerShell functions, see &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/tags/functions/" target="_blank"&gt;this collection of Hey, Scripting Guy! Blog posts&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Save the function into a .ps1 script file&lt;/h2&gt;
&lt;p&gt;So suppose you find a well-written function and you want to be able to use it in the Windows PowerShell console. A well-written Windows PowerShell function will, in fact, act and behave like a Windows PowerShell cmdlet. So bringing it into the Windows PowerShell console will enhance the interactive use experience of Windows PowerShell.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s go back to the &lt;a href="http://gallery.technet.microsoft.com/scriptcenter/2a631d72-206d-4036-a3f2-2e150f297515" target="_blank"&gt;Set-ScreenResolution function&lt;/a&gt; that I used last week (written by Andy Schneider). I go to the Scripting Guys Script Repository, find the &lt;strong&gt;Set-ScreenResolution&lt;/strong&gt; script and copy it to the clipboard. Now, I paste it into the Windows PowerShell ISE, and I save it with a file name like Set-ScreenResolutionFunction.ps1. Here is the script:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/7103.hsg_2D00_5_2D00_13_2D00_13_2D00_01.png"&gt;&lt;img title="Image of script" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/7103.hsg_2D00_5_2D00_13_2D00_13_2D00_01.png" alt="Image of script" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Dot source the script file&lt;/h2&gt;
&lt;p&gt;When I have the function stored in a script file, I can use the function in my Windows PowerShell console, or even in another Windows PowerShell script. The key to doing this is to store the script file that contains the function in an easily locatable folder. For me, that folder is off the root of drive C (C:\fso). I have used this folder for my scratch folder for over a decade.&lt;/p&gt;
&lt;h3&gt;Keys to success for using dot sourcing&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Save the function into a script file with a similar name to the function.&lt;/li&gt;
&lt;li&gt;Save the script file that contains the function in an easily accessed location.&lt;/li&gt;
&lt;li&gt;Make sure that the script file contains only the function, and no &amp;ldquo;entry code&amp;rdquo; that will automatically launch the function.&lt;/li&gt;
&lt;li&gt;Dot source functions into scripts that may have code that changes for ease of update.&lt;/li&gt;
&lt;li&gt;Use the syntax: period, space, path to script (&amp;lt;.&amp;gt;&amp;lt;space&amp;gt;&amp;lt;path&amp;gt;).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To dot source the Set-ScreenResolutionFunction.ps1 script into the Windows PowerShell console, I use the syntax shown here:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;strong&gt;.&lt;/strong&gt; C:\fso\Set-ScreenResolutionFunction.ps1&lt;/p&gt;
&lt;p&gt;To call the &lt;strong&gt;Set-ScreenResolution&lt;/strong&gt; function, I type the function name, just like I would do with a regular Windows PowerShell cmdlet. In fact, tab expansion even works. This is shown here:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Set-ScreenResolution -Width 800 -Height 600&lt;/p&gt;
&lt;p&gt;This technique is shown in the image that follows.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3833.hsg_2D00_5_2D00_13_2D00_13_2D00_02.png"&gt;&lt;img title="Image of script" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3833.hsg_2D00_5_2D00_13_2D00_13_2D00_02.png" alt="Image of script" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I can also use this technique in the Windows PowerShell ISE. In the image that follows, I dot source the Set-ScreenResolutionFunction.ps1 script into my script.&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:12px;"&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/7416.hsg_2D00_5_2D00_13_2D00_13_2D00_03.png"&gt;&lt;img title="Image of script" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/7416.hsg_2D00_5_2D00_13_2D00_13_2D00_03.png" alt="Image of script" /&gt;&lt;/a&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Well, that is about all for now. Now What Do I Do? Week will continue tomorrow when I will continue to talk about using Windows PowerShell functions.&lt;/p&gt;
&lt;p&gt;I invite you to follow me on &lt;a href="http://bit.ly/scriptingguystwitter" target="_blank"&gt;Twitter&lt;/a&gt; and &lt;a href="http://bit.ly/scriptingguysfacebook" target="_blank"&gt;Facebook&lt;/a&gt;. If you have any questions, send email to me at &lt;a href="mailto:scripter@microsoft.com" target="_blank"&gt;scripter@microsoft.com&lt;/a&gt;, or post your questions on the &lt;a href="http://bit.ly/scriptingforum" target="_blank"&gt;Official Scripting Guys Forum&lt;/a&gt;. See you tomorrow. Until then, peace.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ed Wilson, Microsoft Scripting Guy&lt;/strong&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3570668" width="1" height="1" alt="" /&gt;</description></item><item><title>Weekend Scripter: Playing with PowerShell's Get-Variable Cmdlet</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2013/05/11/weekend-scripter-playing-with-powershell-s-get-variable-cmdlet.aspx</link><pubDate>Sat, 11 May 2013 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:23434</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;strong style="font-size:12px;"&gt;Summary&lt;/strong&gt;&lt;span style="font-size:12px;"&gt;: Microsoft Scripting Guy, Ed Wilson, spends some time playing around with the &lt;/span&gt;&lt;strong style="font-size:12px;"&gt;Get-Variable&lt;/strong&gt;&lt;span style="font-size:12px;"&gt; cmdlet.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. This morning I am doing something a little different. Instead of drinking English Breakfast tea, I woke up feeling like I wanted Oolong tea instead. So I made a pot of Oolong tea with a spoonful of jasmine buds, a half spoon of peppermint leaves, three juniper berries, and half of a crushed cinnamon stick. It is quite invigorating, without being too overbearing.&lt;/p&gt;
&lt;h2&gt;Checking the value of a variable&lt;/h2&gt;
&lt;p&gt;So I am sitting on the lanai in my porch swing, and I just finished checking the email for the &lt;a href="mailto:scripter@microsoft.com" target="_blank"&gt;scripter@microsoft.com&lt;/a&gt; email alias. I received an email asking why I would bother using the &lt;strong&gt;Get-Variable&lt;/strong&gt; cmdlet, when I can simply reference the variable to see the value? The reason is that there are many more things I need to do with variables than simply see the value contained inside the variable. The following example assigns a directory listing to the &lt;strong&gt;$dir&lt;/strong&gt; variable:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$dir = dir -Directory | ? lastwritetime -gt $([datetime]&amp;#39;4/1/13&amp;#39;)&lt;/p&gt;
&lt;p&gt;To see the value that is contained in the &lt;strong&gt;$dir&lt;/strong&gt; variable, I can type &lt;strong&gt;$dir&lt;/strong&gt;. The command and the output are shown in the image that follows.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/7144.hsg_2D00_5_2D00_11_2D00_13_2D00_01.png"&gt;&lt;img title="Image of command output" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/7144.hsg_2D00_5_2D00_11_2D00_13_2D00_01.png" alt="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Use Get-Variable&lt;/h3&gt;
&lt;p&gt;I can also do this by using the &lt;strong&gt;Get-Variable&lt;/strong&gt; cmdlet. When use &lt;strong&gt;Get-Variable&lt;/strong&gt;, both the name and the value appear. To return only the value, I group the expression, and get the &lt;strong&gt;Value&lt;/strong&gt;&lt;em&gt; &lt;/em&gt;property as shown here:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;(Get-Variable dir).value&lt;/p&gt;
&lt;p&gt;This command and the associated output are shown in the image that follows.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/8308.hsg_2D00_5_2D00_11_2D00_13_2D00_02.png"&gt;&lt;img title="Image of command output" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/8308.hsg_2D00_5_2D00_11_2D00_13_2D00_02.png" alt="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Use the Variable provider&lt;/h3&gt;
&lt;p&gt;But there are other ways to retrieve values from Windows PowerShell variables. For example, I can use the &lt;strong&gt;Variable&lt;/strong&gt; provider and access the value from the Windows PowerShell Variable drive. I do this by using the command shown here:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$variable:dir&lt;/p&gt;
&lt;p&gt;The command and the output are shown in the following image.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/1781.hsg_2D00_5_2D00_11_2D00_13_2D00_03.png"&gt;&lt;img title="Image of command output" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/1781.hsg_2D00_5_2D00_11_2D00_13_2D00_03.png" alt="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Because the &lt;strong&gt;Variable&lt;/strong&gt; provider creates a PSDrive named &lt;strong&gt;Variable&lt;/strong&gt;, I can use the standard Windows PowerShell cmdlets to work with the variable. For example, I can use &lt;strong&gt;Get-Item &lt;/strong&gt;as shown in this example:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-Item -Path Variable:\dir&lt;/p&gt;
&lt;p&gt;But if I only want the value of the &lt;strong&gt;Dir&lt;/strong&gt; variable, I need to select the &lt;strong&gt;Value&lt;/strong&gt; property:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;(Get-Item -Path Variable:\dir).value&lt;/p&gt;
&lt;p&gt;The commands and associated output are shown in the image that follows.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/2746.hsg_2D00_5_2D00_11_2D00_13_2D00_04.png"&gt;&lt;img title="Image of command output" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/2746.hsg_2D00_5_2D00_11_2D00_13_2D00_04.png" alt="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;One of the cooler things to do is to use the &lt;strong&gt;Get-Content&lt;/strong&gt; cmdlet to obtain the contents of the variable. When using this technique, only the first value from the array returns. This is shown here:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PS C:\&amp;gt; Get-Content variable:\dir&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Directory: C:\&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Mode&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LastWriteTime&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Length Name&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;----&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-------------&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ------ ----&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;d----&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4/23/2013&amp;nbsp; 12:41 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fso&lt;/p&gt;
&lt;h2&gt;Examining the type of a variable&lt;/h2&gt;
&lt;p&gt;I am sure you know that there are different types of variables in Windows PowerShell. If I use the &lt;strong&gt;Get-Variable&lt;/strong&gt; cmdlet, pipe the results to the &lt;strong&gt;Format-List&lt;/strong&gt; cmdlet, and choose all of the properties, I obtain some pretty interesting information. This is shown here:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PS C:\&amp;gt; Get-Variable dir | fl *&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PSPath&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Microsoft.PowerShell.Core\Variable::dir&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PSDrive&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Variable&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PSProvider&amp;nbsp;&amp;nbsp;&amp;nbsp; : Microsoft.PowerShell.Core\Variable&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PSIsContainer : False&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Name&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : dir&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Description&amp;nbsp;&amp;nbsp; :&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Value&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : {fso, fsox, Program Files, Program Files (x86)...}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Visibility&amp;nbsp;&amp;nbsp;&amp;nbsp; : Public&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Module&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;ModuleName&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Options&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : None&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Attributes&amp;nbsp;&amp;nbsp;&amp;nbsp; : {}&lt;/p&gt;
&lt;p&gt;If I take the &lt;strong&gt;$dir&lt;/strong&gt; variable and pipe it to the &lt;strong&gt;Get-Member&lt;/strong&gt; cmdlet, it returns information about the objects that are contained in the variable, and not about the variable itself.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$dir | get-member&lt;/p&gt;
&lt;p&gt;The command and output from the command are shown in the image that follows.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3056.hsg_2D00_5_2D00_11_2D00_13_2D00_05.png"&gt;&lt;img title="Image of command output" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3056.hsg_2D00_5_2D00_11_2D00_13_2D00_05.png" alt="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To find information about the variable itself, I use &lt;strong&gt;Get-Variable&lt;/strong&gt; to return the variable, and then I pipe the result to the &lt;strong&gt;Get-Member&lt;/strong&gt; cmdlet:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-Variable dir | Get-Member&lt;/p&gt;
&lt;p&gt;The command and output from the command are shown here.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/1768.hsg_2D00_5_2D00_11_2D00_13_2D00_06.png"&gt;&lt;img title="Image of command output" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/1768.hsg_2D00_5_2D00_11_2D00_13_2D00_06.png" alt="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Finding different types of variables&lt;/h2&gt;
&lt;p&gt;Unfortunately, this does not return anything about the type of Windows PowerShell variable. So what is the easy way to find the variable type? Use the &lt;strong&gt;Get-Variable&lt;/strong&gt; cmdlet and pipe the returned objects to the &lt;strong&gt;Get-Member&lt;/strong&gt; cmdlet. Next, I select only the &lt;strong&gt;TypeName&lt;/strong&gt; property, and I use the &lt;strong&gt;Unique&lt;/strong&gt; switch to ensure only unique instances return. Here is the command and the results:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PS C:\&amp;gt; Get-Variable | Get-Member | select typename -Unique&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;TypeName&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;--------&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;System.Management.Automation.PSVariable&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;System.Management.Automation.QuestionMarkVariable&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;System.Management.Automation.LocalVariable&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;System.Management.Automation.SessionStateCapacityVariable&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;System.Management.Automation.NullVariable&lt;/p&gt;
&lt;p&gt;When I know the different types of variables, I can use Windows PowerShell to list a particular type of variable. To do this, I pipe the results of &lt;strong&gt;Get-Variable&lt;/strong&gt; to the &lt;strong&gt;Where-Object&lt;/strong&gt;. In my &lt;strong&gt;Where-Object&lt;/strong&gt; filter, I use the &lt;strong&gt;PSObject&lt;/strong&gt;&lt;em&gt; &lt;/em&gt;property so I can reference the underlying type. This technique is shown here where I find all variables of the type &lt;strong&gt;LocalVariable&lt;/strong&gt;&lt;em&gt;. &lt;/em&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-Variable | where {$_.psobject.typenames -match &amp;#39;local&amp;#39;}&lt;/p&gt;
&lt;p&gt;The command and output from the command are shown here.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0755.hsg_2D00_5_2D00_11_2D00_13_2D00_07.png"&gt;&lt;img title="Image of command output" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0755.hsg_2D00_5_2D00_11_2D00_13_2D00_07.png" alt="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Join me tomorrow for the exciting conclusion to the Windows PowerShell and Security series by Yuri Diogenes and Tom Schinder. To catch up, read &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/tags/yuri+diogenes/"&gt;the two previous posts in this series&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I invite you to follow me on &lt;a href="http://bit.ly/scriptingguystwitter" target="_blank"&gt;Twitter&lt;/a&gt; and &lt;a href="http://bit.ly/scriptingguysfacebook" target="_blank"&gt;Facebook&lt;/a&gt;. If you have any questions, send email to me at &lt;a href="mailto:scripter@microsoft.com" target="_blank"&gt;scripter@microsoft.com&lt;/a&gt;, or post your questions on the &lt;a href="http://bit.ly/scriptingforum" target="_blank"&gt;Official Scripting Guys Forum&lt;/a&gt;. See you tomorrow. Until then, peace.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ed Wilson, Microsoft Scripting Guy&lt;/strong&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3570611" width="1" height="1" alt="" /&gt;</description></item><item><title>Weekend Scripter: Improve Performance When Combining PowerShell Arrays</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2013/04/27/weekend-scripter-improve-performance-when-combining-powershell-arrays.aspx</link><pubDate>Sat, 27 Apr 2013 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:23109</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;span style="font-size:12px;"&gt;&lt;strong&gt;Summary&lt;/strong&gt;: Microsoft premier field engineer, Chris Wu, talks about combining Windows PowerShell arrays.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. Chris Wu, a Microsoft PFE, is back to share his knowledge. See &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/tags/chris+wu/http:/blogs.technet.com/b/heyscriptingguy/archive/tags/chris+wu/" target="_blank"&gt;previous Hey, Scripting Guy! Blog guest posts&lt;/a&gt; from Chris.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Here is contact information for Chris:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Twitter: &lt;a href="https://twitter.com/chwu_ms"&gt;https://twitter.com/chwu_ms&lt;/a&gt;&lt;br /&gt; Facebook: &lt;a href="https://www.facebook.com/mschwu"&gt;https://www.facebook.com/mschwu&lt;/a&gt;&lt;br /&gt; LinkedIn: &lt;a href="http://ca.linkedin.com/in/mschwu"&gt;http://ca.linkedin.com/in/mschwu&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Take it away Chris&amp;hellip;&lt;/p&gt;
&lt;p&gt;While teaching a Windows PowerShell workshop, I was asked about how to combine two arrays of different objects (which share one key property) into one that contains objects with properties from both source objects. One real world scenario is to merge information retrieved from Active Directory (a list of Active Directory users and their properties) and Exchange Server (mailboxes).&lt;/p&gt;
&lt;p&gt;The current approach by the student is to use two-level loops, which has seen performance issues when source arrays become huge in size (the following code snippet uses dummy data for demonstration purposes).&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$ADList = @&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;chwu,chwu@microsoft.com,Chris Wu&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;tst1,,Test User1&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;tst2,tst2@contoso.com,Test User2&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;quot;@ | ConvertFrom-Csv -Header Name,mail,CN&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$EXList = @&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;chwu,ex1.contoso.com&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;tst2,ex2.contoso.com&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;quot;@ | ConvertFrom-Csv -Header Name,MailServer&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$Result = @()&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;foreach($ad in $ADList) {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp; $Match = $false&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp; foreach($ex in $EXList) {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($ad.Name -eq $ex.Name) {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $Result += New-Object PSObject -Property @{Name=$ad.Name; mail=$ad.mail; CN=$ad.CN; MailServer=$ex.MailServer}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $Match = $true&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp; }&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp; if(-not $Match) {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $Result += New-Object PSObject -Property @{Name=$ad.Name; mail=$ad.mail; CN=$ad.CN}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp; }&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3716.wes_2D00_4_2D00_27_2D00_13_2D00_1.png"&gt;&lt;img style="border:0px currentColor;" title="Image of command output" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3716.wes_2D00_4_2D00_27_2D00_13_2D00_1.png" alt="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In this post, I will explore several options to improve the performance and cleanness of this code snippet.&lt;/p&gt;
&lt;p&gt;The first thing we can do is remove the use of the &lt;strong&gt;$Result&lt;/strong&gt; array, which has two drawbacks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Every assignment operation will create a new array in memory with data copied from the source, which is inefficient.&lt;/li&gt;
&lt;li&gt;It defeats the streaming benefit of the WindowsPowerShell pipeline because it returns all objects as a whole at the end of the processing. A best practice in Windows PowerShell is to emit an individual object whenever it&amp;rsquo;s ready.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Another performance issue stems from the use of an inner loop to search for a matching record in the second array, which basically multiplies the total number of iterations. We can utilize a hash table for faster lookup. The &lt;strong&gt;Group-Object&lt;/strong&gt; cmdlet offers a convenient &lt;strong&gt;AsHashTable &lt;/strong&gt;parameter that can be used here.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/8512.wes_2D00_4_2D00_27_2D00_13_2D00_2.png"&gt;&lt;img style="border:0px currentColor;" title="Image of command output" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/8512.wes_2D00_4_2D00_27_2D00_13_2D00_2.png" alt="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Please be warned that the value portion of each entry is an array of matching records. If we are grouping records by using a property with unique values (such as &lt;strong&gt;SamAccountName&lt;/strong&gt;), those arrays will apparently contains one single element each.&lt;/p&gt;
&lt;p&gt;So an enhanced version of the code snippet is like this (with the constructing source arrays removed):&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$h = $EXList | Group-Object -Property Name -AsHashTable&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$ADList | %{&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp; if($h[$_.Name]) {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; New-Object PSObject -Property @{Name=$_.Name; mail=$_.mail; CN=$_.CN; MailServer=$h[$_.Name][0].MailServer}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp; } else {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; New-Object PSObject -Property @{Name=$_.Name; mail=$_.mail; CN=$_.CN}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp; }&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p&gt;The last (but not the least) idea is to sort both arrays based on the key property (user name) beforehand, then we can pair records in a single iteration. Note that in this particular example, users found in Active Directory is a superset of users in Exchange, so we need a pointer variable to deal with this little quirk.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$ADList = @&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;chwu,chwu@microsoft.com,Chris Wu&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;tst1,,Test User1&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;tst2,tst2@contoso.com,Test User2&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;quot;@ | ConvertFrom-Csv -Header Name,mail,CN | Sort-Object -Property Name&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$EXList = @&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;chwu,ex1.contoso.com&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;tst2,ex2.contoso.com&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;quot;@ | ConvertFrom-Csv -Header Name,MailServer | Sort-Object -Property Name&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$ADList | % {$p = 0} {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp; if($_.Name -eq $EXList[$p].Name) {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; New-Object PSObject -Property @{Name=$_.Name; mail=$_.mail; CN=$_.CN; MailServer=$EXList[$p].MailServer}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $p++&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp; } else {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; New-Object PSObject -Property @{Name=$_.Name; mail=$_.mail; CN=$_.CN}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp; }&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p&gt;The last two snippets perform much better than the original one, but which one is faster remains a question (I haven&amp;rsquo;t tested them against large arrays just yet). I would like to hear about your results, and I welcome your thoughts and ideas.&lt;/p&gt;
&lt;p&gt;~Chris&lt;/p&gt;
&lt;p&gt;Thanks Chris excellent blog post. Join me tomorrow for more cool Windows PowerShell stuff.&lt;/p&gt;
&lt;p&gt;I invite you to follow me on &lt;a href="http://bit.ly/scriptingguystwitter" target="_blank"&gt;Twitter&lt;/a&gt; and &lt;a href="http://bit.ly/scriptingguysfacebook" target="_blank"&gt;Facebook&lt;/a&gt;. If you have any questions, send email to me at &lt;a href="mailto:scripter@microsoft.com" target="_blank"&gt;scripter@microsoft.com&lt;/a&gt;, or post your questions on the &lt;a href="http://bit.ly/scriptingforum" target="_blank"&gt;Official Scripting Guys Forum&lt;/a&gt;. See you tomorrow. Until then, peace.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ed Wilson, Microsoft Scripting Guy&lt;/strong&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3566535" width="1" height="1" alt="" /&gt;</description></item><item><title>Weekend Scripter: Pick Comments from a PowerShell Script</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2013/04/13/weekend-scripter-pick-comments-from-a-powershell-script.aspx</link><pubDate>Sat, 13 Apr 2013 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:22793</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;strong style="font-size:12px;"&gt;Summary&lt;/strong&gt;&lt;span style="font-size:12px;"&gt;: Guest blogger, Bob Stevens, shares a script to pick out comments from a Windows PowerShell script.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. Today we have a new guest blogger, Bob Stevens. I made Bob&amp;rsquo;s virtual acquaintance recently when I did a Live Meeting presentation to the &lt;a href="http://www.tcposhug.com/" target="_blank"&gt;Twin Cities PowerShell User Group.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here is Bob&amp;rsquo;s contact information:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;span style="font-size:12px;"&gt;Blog: &lt;/span&gt;&lt;a href="http://stuckinmypowershell.blogspot.com/" target="_blank"&gt;Help! I&amp;rsquo;m Stuck in My Powershell!&lt;/a&gt;&lt;br /&gt; Twitter: &lt;a href="https://twitter.com/B_stevens6" target="_blank"&gt;@B_stevens6&lt;/a&gt;&lt;br /&gt; LinkedIn: &lt;a href="http://www.linkedin.com/profile/edit?trk=hb_tab_pro_top" target="_blank"&gt;Robert Stevens&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The floor is yours, Bob&amp;hellip;&lt;/p&gt;
&lt;p&gt;As a local Help Desk technician, I run into many repetitive support tasks. From low toners to Internet Explorer issues, I have done it all. About three months ago I discovered that I could use PowerShell to automate a number of these tasks, thereby freeing my time for some of the more unusual issues. Fortunately, all of the computers at my site have Windows PowerShell&amp;nbsp;2.0 installed, so it was a matter of ensuring that they can run scripts. This can be done by changing the &lt;strong&gt;Set-ExecutionPolicy&lt;/strong&gt; cmdlet to &lt;strong&gt;Unrestricted&lt;/strong&gt; in the following manner:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Set-ExecutionPolicy Unrestricted&lt;/p&gt;
&lt;p&gt;When the work is done, switch it back to the organization default with:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Set-ExecutionPolicy Remote-Signed&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Set-ExecutionPolicy&lt;/strong&gt; governs which scripts can be run on any given system. By setting it as &lt;strong&gt;Unrestricted&lt;/strong&gt;, I am removing all restrictions. I switch it back to &lt;strong&gt;Remote-Signed&lt;/strong&gt; to prevent users from running scripts that can potentially damage a system, thereby presenting a potential for data loss.&lt;/p&gt;
&lt;p&gt;Fast forward three months and multiple scripts later&amp;hellip;&lt;/p&gt;
&lt;p&gt;It dawned on me that I would need to create documentation for each of these scripts. Documentation provides my coworkers with the insight they need to understand the purpose and functionality of my work and to pick up where I left off should the script need to be altered. Thankfully, like a good Windows PowerShell scripter, I commented liberally throughout my scripts to ensure that I knew where I would need to alter it in the future. To this end I started working on a script to pull comments. I knew that I habitually use single line comments for documentation and block comments for commenting out blocks of code. Happy accident because the script I devised only pulls the first and the last lines of a block comment.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;strong&gt;Note&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;For simplicity, I name all directories a variation of &lt;strong&gt;&amp;ldquo;foo&amp;rdquo;&lt;/strong&gt; and all input files a variation of &lt;strong&gt;&amp;ldquo;foo.*&amp;rdquo;&lt;/strong&gt;. You can set foo as whatever you want.&lt;/p&gt;
&lt;p&gt;As usual I started with setting my location:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Set-Location &amp;ldquo;C:\foo&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Next we set our source script file as a variable. I use variables in my scripts to enable me to change one line of code, rather than five lines, thereby reducing the chance of an error. Variables are defined by the dollar sign (&lt;strong&gt;$&lt;/strong&gt;).&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$script = &amp;ldquo;foo.ps1&amp;rdquo;&lt;/p&gt;
&lt;p&gt;We need to define an output variable as &lt;strong&gt;$out&lt;/strong&gt;. Note that I used the &lt;strong&gt;$script&lt;/strong&gt; variable in the variable value. This will result in the file name of &lt;strong&gt;foo.ps1 comments.txt&lt;/strong&gt;. This is to differentiate between output files. For this to work, there must be a space between &lt;strong&gt;$script&lt;/strong&gt; and &lt;strong&gt;comments.txt&lt;/strong&gt;:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$out = &amp;ldquo;$script comments.txt&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Now that we have defined the output file name, we need to create the output file itself, and I do this with the &lt;strong&gt;New-Item&lt;/strong&gt; cmdlet. Of course, we need to define the object as a file&amp;mdash;otherwise we get a dialog box asking us if it&amp;rsquo;s a file or folder:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;New-Item &amp;ldquo;out&amp;rdquo; -ItemType File&lt;/p&gt;
&lt;p&gt;Now our preparation is complete:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Set-Location &amp;quot;c:\foo&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$script = &amp;quot;foo.ps1&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$out = &amp;quot;$script comments.txt&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;New-Item &amp;quot;$out&amp;quot; -ItemType File&lt;/p&gt;
&lt;p&gt;We need to pull the content of our source file with the &lt;strong&gt;Get-Content&lt;/strong&gt; cmdlet:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-Content $script&lt;/p&gt;
&lt;p&gt;The next line is to prevent Windows PowerShell from appending the output to output that already exists in the variable by creating an array, this is done with the array (&lt;strong&gt;@&lt;/strong&gt;) operator, followed by both parentheses:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$comments = @()&lt;/p&gt;
&lt;p&gt;This is where the magic takes place. We need to use the &lt;strong&gt;Select-String&lt;/strong&gt; cmdlet. This command requires two parameters: &lt;strong&gt;Pattern&lt;/strong&gt; and &lt;strong&gt;File&lt;/strong&gt;. Both values need to be quoted if you are not using a variable to define it. As we are searching for comments, we are going to select strings that contain &lt;strong&gt;&amp;ldquo;#&amp;rdquo;&lt;/strong&gt;:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Select-String -Pattern &amp;ldquo;#&amp;rdquo; $script&lt;/p&gt;
&lt;p&gt;This is a bit more complex, and it requires stringing three commands together, so we use the pipe (&lt;strong&gt;|&lt;/strong&gt;) operator. The pipe operator merely states do &amp;ldquo;this&amp;rdquo; and then do &amp;ldquo;that&amp;rdquo; with the output of &amp;ldquo;this.&amp;rdquo; Pipe operators must always have a space preceding and succeeding it:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Select-String -Pattern &amp;ldquo;#&amp;rdquo; $script |&lt;/p&gt;
&lt;p&gt;For our purposes, we are going to say, &amp;ldquo;For each object, do this.&amp;rdquo; Coincidentally (or not), Microsoft decided to add a &lt;strong&gt;Foreach-Object&lt;/strong&gt; cmdlet for just this purpose! And everything that you are doing with &lt;strong&gt;Foreach-Object&lt;/strong&gt; must be in braces to group them together:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Select-String - Pattern &amp;ldquo;#&amp;rdquo; $script |&lt;/p&gt;
&lt;p style="padding-left:60px;"&gt;Foreach-Object {}&lt;/p&gt;
&lt;p&gt;When we string commands like this together, formatting is important&amp;mdash;not for functionality, but for readability. Now we need to comment the full line where &lt;strong&gt;&amp;ldquo;#&amp;rdquo;&lt;/strong&gt; appears. It is important to note that you must use &lt;strong&gt;&amp;ldquo;+=&amp;rdquo;&lt;/strong&gt;, or you will end up with an empty file:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Select-String - Pattern &amp;ldquo;#&amp;rdquo; $script |&lt;/p&gt;
&lt;p style="padding-left:60px;"&gt;Foreach-Object {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$comments += $_.line&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p&gt;We need to tell Windows PowerShell to grab everything after &lt;strong&gt;&amp;ldquo;#&amp;rdquo; &lt;/strong&gt;in that string. This is tricky, but it can be done with the &lt;strong&gt;context.postcontext&lt;/strong&gt; definition:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Select-String - Pattern &amp;ldquo;#&amp;rdquo; $script |&lt;/p&gt;
&lt;p style="padding-left:60px;"&gt;Foreach-Object {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$comments += $_.line&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$comments += $_.context.postcontext&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p&gt;We now need to tell Windows PowerShell to extract everything that we just defined within the &lt;strong&gt;Foreach-Object&lt;/strong&gt; curly brackets:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Select-String - Pattern &amp;ldquo;#&amp;rdquo; $script |&lt;/p&gt;
&lt;p style="padding-left:60px;"&gt;Foreach-Object {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$comments += $_.line&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$comments += $_.context.postcontext&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$comments&lt;/p&gt;
&lt;p&gt;Finally, we dump our output into the output file &lt;strong&gt;$out&lt;/strong&gt; with the &lt;strong&gt;Set-Content&lt;/strong&gt; cmdlet:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Select-String - Pattern &amp;ldquo;#&amp;rdquo; $script |&lt;/p&gt;
&lt;p style="padding-left:60px;"&gt;Foreach-Object {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$comments += $_.line&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$comments += $_.context.postcontext&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$comments | Set-Content $out&lt;/p&gt;
&lt;p&gt;The complete script looks something like this:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Set-Location &amp;quot;c:\foo&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$script = &amp;quot;foo.ps1&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$out = &amp;quot;$script comments.txt&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;New-Item &amp;quot;$out&amp;quot; -ItemType File&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-Content $script&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$comments = @()&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Select-String -Pattern &amp;quot;#&amp;quot; $script |&lt;/p&gt;
&lt;p style="padding-left:60px;"&gt;Foreach-Object {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$comments += $_.line&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$comments += $_.context.postcontext&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$comments | Set-Content $out&lt;/p&gt;
&lt;p&gt;The result should take the following input:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3426.wes_2D00_4_2D00_13_2D00_13_2D00_1.png"&gt;&lt;img style="border:0px currentColor;" title="Image of script" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3426.wes_2D00_4_2D00_13_2D00_13_2D00_1.png" alt="Image of script" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And give you the following output (&lt;strong&gt;Select-String -pattern &amp;ldquo;#&amp;rdquo;&lt;/strong&gt; shows up because it contains a &lt;strong&gt;&amp;ldquo;#&amp;rdquo;&lt;/strong&gt;):&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/5773.wes_2D00_4_2D00_13_2D00_13_2D00_2.png"&gt;&lt;img style="border:0px currentColor;" title="Image of command output" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/5773.wes_2D00_4_2D00_13_2D00_13_2D00_2.png" alt="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This saved me an hour now and countless future hours that I would spend extracting comments for documentation.&lt;/p&gt;
&lt;p&gt;When I was verifying my work, I ran across the following note to myself stating that I referenced a Rob Campbell in another script. Some of the code made it in here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Rob Campbell, Mjolinor: &lt;a href="http://social.technet.microsoft.com/Forums/en-US/winserverpowershell/thread/b41bfe7f-2ec3-428e-8a79-962afa076067/" target="_blank"&gt;How do you extract data from a txt file with powershell&lt;/a&gt;. As always, input is always appreciated.&lt;/p&gt;
&lt;p&gt;Thank you for your time.&amp;nbsp;I uploaded the complete script to the Script Center Repository: &lt;a href="http://gallery.technet.microsoft.com/scriptcenter/Extracting-comments-from-a-149af1ea" target="_blank"&gt;Extracting Comments from a Script with PowerShell&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;~Bob&lt;em&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Thank you, Bob, for sharing your script and your insight with us today. Join us tomorrow when Bob talks about a script he wrote to clean up user profiles. It is cool, and you do not want to miss it.&lt;/p&gt;
&lt;p&gt;I invite you to follow me on &lt;a href="http://bit.ly/scriptingguystwitter" target="_blank"&gt;Twitter&lt;/a&gt; and &lt;a href="http://bit.ly/scriptingguysfacebook" target="_blank"&gt;Facebook&lt;/a&gt;. If you have any questions, send email to me at &lt;a href="mailto:scripter@microsoft.com" target="_blank"&gt;scripter@microsoft.com&lt;/a&gt;, or post your questions on the &lt;a href="http://bit.ly/scriptingforum" target="_blank"&gt;Official Scripting Guys Forum&lt;/a&gt;. See you tomorrow. Until then, peace.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ed Wilson, Microsoft Scripting Guy&lt;/strong&gt;&lt;span style="font-size:12px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3564133" width="1" height="1" alt="" /&gt;</description></item><item><title>Named Arguments for PowerShell Functions: Best Practices</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2013/04/11/named-arguments-for-powershell-functions-best-practices.aspx</link><pubDate>Thu, 11 Apr 2013 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:22719</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;strong style="font-size:12px;"&gt;Summary&lt;/strong&gt;&lt;span style="font-size:12px;"&gt;: Microsoft Scripting Guy, Ed Wilson, talks about using named arguments in Windows PowerShell functions.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. If I go to the trouble of writing a Windows PowerShell script, I generally do not use unnamed arguments (such as &lt;strong&gt;$args&lt;/strong&gt; as I illustrated yesterday in &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2013/04/10/accepting-arguments-for-powershell-functions-best-practices.aspx" target="_blank"&gt;Accepting Arguments for PowerShell Functions: Best Practices&lt;/a&gt;). Instead I create named arguments for my functions. It is just so much more powerful, and so much more flexible. Besides, I can still pass values appositionally in an unnamed fashion if I wish to do so.&lt;/p&gt;
&lt;h2&gt;Create a named argument in five easy steps&lt;/h2&gt;
&lt;p&gt;In yesterday&amp;#39;s blog,&amp;nbsp;I said that there are only three requirements to create a function in Windows PowerShell:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The &lt;strong&gt;Function&lt;/strong&gt; keyword&lt;/li&gt;
&lt;li&gt;The name of the function&lt;/li&gt;
&lt;li&gt;A script block&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To create a named argument in a Windows PowerShell function, I need only two &amp;nbsp;additional things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The &lt;strong&gt;Param&lt;/strong&gt; keyword&lt;/li&gt;
&lt;li&gt;A variable to hold the argument inside a pair of parentheses&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The following script illustrates this technique:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Function myfunction&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;{&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;Param($myargument)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;quot;This value of `$myargument is $myargument&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:small;"&gt;To use &lt;strong style="font-size:12px;"&gt;MyFunction&lt;/strong&gt;, I first have to run the script. This loads the function into memory and makes it available via the function PSDrive. Because I have not saved the script containing the function, when I run the script, it appears in the Console pane below the Script pane. When the script runs, the Windows PowerShell prompt returns, and I can call the function by typing the name of the function. I then supply a value for the argument by typing it. This is shown in the image that follows.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/4617.hsg_2D00_4_2D00_11_2D00_13_2D00_01.png"&gt;&lt;img style="border:0px currentColor;" title="Image of script" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/4617.hsg_2D00_4_2D00_11_2D00_13_2D00_01.png" alt="Image of script" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Keep in mind that tab expansion works here. So I do not have to type the entire name of &lt;strong&gt;MyFunction&lt;/strong&gt;, nor do I need to type the complete name of &lt;strong&gt;MyArgument&lt;/strong&gt;&lt;em&gt;. &lt;/em&gt;In fact, I only had to type &lt;strong&gt;my&lt;/strong&gt; and press the Tab key to get the &lt;strong&gt;MyFunction&lt;/strong&gt;&lt;em&gt; &lt;/em&gt;command onto the command line. When I type the hyphen (&lt;strong&gt;&amp;ndash;&lt;/strong&gt;) for the named argument (parameter) a pop-up list appears, as shown in the following image.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/6153.hsg_2D00_4_2D00_11_2D00_13_2D00_02.png"&gt;&lt;img style="border:0px currentColor;" title="Image of script" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/6153.hsg_2D00_4_2D00_11_2D00_13_2D00_02.png" alt="Image of script" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The advantage of using named arguments (parameters) is that I do not need to name the parameter if I do not want to. I can use it as a positional parameter. In this manner, it behaves like an unnamed argument (&lt;strong&gt;$args&lt;/strong&gt;). This is shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;span style="font-size:small;"&gt;PS C:\&amp;gt; myfunction &amp;quot;this is a&amp;nbsp; string&amp;quot;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;span style="font-size:small;"&gt;This value of $myargument is this is a&amp;nbsp; string&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:small;"&gt;Because creating named parameters in Windows PowerShell is so easy, and because using the &lt;strong style="font-size:12px;"&gt;Param&lt;/strong&gt;&lt;em style="font-size:12px;"&gt; &lt;/em&gt;keyword is the entry into the world of advanced functions, I never use &lt;strong style="font-size:12px;"&gt;$args&lt;/strong&gt; in a Windows PowerShell script. Because it is an automatic variable that becomes available in certain circumstances, using &lt;strong style="font-size:12px;"&gt;$args&lt;/strong&gt; is more difficult to understand because nothing has been created in the script. It is just there.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:small;"&gt;On the other hand, because the &lt;strong&gt;Param&lt;/strong&gt;&lt;em&gt; &lt;/em&gt;block is declared and available for inspection, it makes sense, and is easier to understand. If I begin with a script that uses &lt;strong&gt;$args&lt;/strong&gt; and I later decide that I need to add functionality, I will have to add a &lt;strong&gt;Param&lt;/strong&gt;&lt;em&gt; &lt;/em&gt;block to get access to advanced features.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Join me tomorrow when I will welcome guest bloggers Yuri Diogenes and Tom Shinder back with the second installment in their security series. If you want to refresh your memory, check out their first installment in the series:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2013/03/29/security-series-using-powershell-to-protect-your-private-cloud-infrastructure.aspx" target="_blank"&gt;Security Series: Using PowerShell to Protect Your Private Cloud Infrastructure&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I invite you to follow me on &lt;a href="http://bit.ly/scriptingguystwitter" target="_blank"&gt;Twitter&lt;/a&gt; and &lt;a href="http://bit.ly/scriptingguysfacebook" target="_blank"&gt;Facebook&lt;/a&gt;. If you have any questions, send email to me at &lt;a href="mailto:scripter@microsoft.com" target="_blank"&gt;scripter@microsoft.com&lt;/a&gt;, or post your questions on the &lt;a href="http://bit.ly/scriptingforum" target="_blank"&gt;Official Scripting Guys Forum&lt;/a&gt;. See you tomorrow. Until then, peace.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ed Wilson, Microsoft Scripting Guy&lt;/strong&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3564417" width="1" height="1" alt="" /&gt;</description></item><item><title>Accepting Arguments for PowerShell Functions: Best Practices</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2013/04/10/accepting-arguments-for-powershell-functions-best-practices.aspx</link><pubDate>Wed, 10 Apr 2013 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:22677</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;strong style="font-size:12px;"&gt;Summary&lt;/strong&gt;&lt;span style="font-size:12px;"&gt;: Microsoft Scripting Guy, Ed Wilson, talks about the best practices surrounding accepting input for a Windows PowerShell function.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. April in the Carolina&amp;rsquo;s is a special time. In fact, it is my favorite time of the year here. This is because the weather is invariably mild. This week, it has been sunny, moderate temperature, mild humidity, and clear skies. The Scripting Neighbors tell me it is perfect golf weather. It is also perfect &amp;ldquo;sit on the lanai and write Windows PowerShell scripts&amp;rdquo; weather. Although I have never had much luck with &lt;a href="http://quoteinvestigator.com/2011/08/01/golf-small-hole/" target="_blank"&gt;putting a small ball into an even smaller hole with equipment not designed for that purpose&lt;/a&gt;, I can compute the trajectory, and force necessary to accomplish the task with a one-line Windows PowerShell command.&lt;/p&gt;
&lt;h2&gt;Passing a value to a Windows PowerShell function&lt;/h2&gt;
&lt;p&gt;If I have a function that I need to pass a value to, I can use the automatic variable &lt;strong&gt;$args&lt;/strong&gt;. This makes the function easy to write and easy to use. The following function uses three steps to create the function. It calls the function keyword, provides a name, and creates a script block that contains code.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;function myfunction&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;{&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;quot;the computer name is $args&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p&gt;In the Windows PowerShell ISE, I run the script (I do not have to save the code into a .ps1 file), and the function loads into memory. I can then call the function directly in the execution pane (the dark blue box that follows) and pass a value to the function when I call it. The command line is shown here:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;myfunction $env:COMPUTERNAME&lt;/p&gt;
&lt;p&gt;The image that follows illustrates creating the function, using &lt;strong&gt;$args&lt;/strong&gt; in the script block, and calling the function from the execution pane.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0880.hsg_2D00_4_2D00_10_2D00_13_2D00_01.png"&gt;&lt;img style="border:0px currentColor;" title="Image of command" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0880.hsg_2D00_4_2D00_10_2D00_13_2D00_01.png" alt="Image of command" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Anything I add following the name of the function populates the &lt;strong&gt;$args&lt;/strong&gt; variable. In the command that follows, I pass the value &lt;strong&gt;mred&lt;/strong&gt;&lt;em&gt; &lt;/em&gt;to the function. Interestingly, I do not have to supply quotation marks when passing the value.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PS C:\&amp;gt; myfunction mred&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;the computer name is mred&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PS C:\&amp;gt; myfunction &amp;quot;mred&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;the computer name is mred&lt;/p&gt;
&lt;p&gt;I can also use the output from the &lt;strong&gt;Get-WmiObject&lt;/strong&gt; cmdlet for input. Therefore, the following code uses WMI to return the computer name and to pass it to the &lt;strong&gt;MyFunction&lt;/strong&gt;&lt;em&gt; &lt;/em&gt;function.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PS C:\&amp;gt; myfunction (gwmi win32_computersystem).name&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;the computer name is EDLT&lt;/p&gt;
&lt;p&gt;One thing to keep in mind, is that when I use the &lt;strong&gt;$args&lt;/strong&gt; automatic variable as illustrated in the &lt;strong&gt;MyFunction&lt;/strong&gt;&lt;em&gt; &lt;/em&gt;function, I cannot pipe input to the function. This can actually be a bit of a problem, because it could be really hard to troubleshoot due to the fact that no error arises. This is shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PS C:\&amp;gt; $env:COMPUTERNAME | myfunction&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;the computer name is&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If I want to pipel input to my function, I use the &lt;strong&gt;$input&lt;/strong&gt; automatic variable. The only change that is required to my function is to change &lt;strong&gt;$args&lt;/strong&gt; to &lt;strong&gt;$input&lt;/strong&gt;, as shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;function afunction&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;{&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;quot;the computer name is $input&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p&gt;I then pipe the input to the function by using the command shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PS C:\&amp;gt; $env:COMPUTERNAME | afunction&lt;/p&gt;
&lt;p&gt;If I attempt to provide positional input to the function instead of piping the input, no error arises, but no value passes either.&lt;/p&gt;
&lt;p&gt;The command and associated output are shown in the image here.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/8880.hsg_2D00_4_2D00_10_2D00_13_2D00_02.png"&gt;&lt;img style="border:0px currentColor;" title="Image of command output" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/8880.hsg_2D00_4_2D00_10_2D00_13_2D00_02.png" alt="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Best Practices Week will continue tomorrow when I will talk some more about Windows PowerShell functions.&lt;/p&gt;
&lt;p&gt;I invite you to follow me on &lt;a href="http://bit.ly/scriptingguystwitter" target="_blank"&gt;Twitter&lt;/a&gt; and &lt;a href="http://bit.ly/scriptingguysfacebook" target="_blank"&gt;Facebook&lt;/a&gt;. If you have any questions, send email to me at &lt;a href="mailto:scripter@microsoft.com" target="_blank"&gt;scripter@microsoft.com&lt;/a&gt;, or post your questions on the &lt;a href="http://bit.ly/scriptingforum" target="_blank"&gt;Official Scripting Guys Forum&lt;/a&gt;. See you tomorrow. Until then, peace.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ed Wilson, Microsoft Scripting Guy&lt;/strong&gt;&lt;span style="font-size:12px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3564373" width="1" height="1" alt="" /&gt;</description></item><item><title>Using PowerShell Functions: Best Practices</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2013/04/09/using-powershell-functions-best-practices.aspx</link><pubDate>Tue, 09 Apr 2013 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:22637</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;strong style="font-size:12px;"&gt;Summary&lt;/strong&gt;&lt;span style="font-size:12px;"&gt;: Microsoft Scripting Guy, Ed Wilson, talks about some best practices for using Windows PowerShell functions.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. Windows PowerShell functions are really powerful, and at the same time, they are incredibly simple to create. This makes Windows PowerShell functions flexible and functional. But this flexibility also means that there is a lot of misunderstanding.&lt;/p&gt;
&lt;h2&gt;A simple function&lt;/h2&gt;
&lt;p&gt;At the low end (in terms of readability, functionality, features, and so on), a Windows PowerShell function is creatable on a single line interactively at the Windows PowerShell console. The minimum number of elements required to create a function are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Function&lt;/strong&gt; keyword&lt;/li&gt;
&lt;li&gt;The name of the function&lt;/li&gt;
&lt;li&gt;A script block&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is it. This means that the following is a legitimate function:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;function a {}&lt;/p&gt;
&lt;p&gt;It does not do anything, but it is legitimate. Running the code at a command prompt in the Windows PowerShell console creates the function. I can then pipe output to it, and even verify that it exists on the Windows PowerShell function PS drive. The following script illustrates these concepts.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PS C:\&amp;gt; function a {}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PS C:\&amp;gt; gps | a&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PS C:\&amp;gt; dir function:a&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;CommandType&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Name&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ModuleName&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;-----------&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ----&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ----------&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Function&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; a&lt;span style="font-size:12px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;Adding functionality to the function&lt;/h2&gt;
&lt;p&gt;I often need to get a view of data, or a snapshot of data, before I return all of the data. Typically, I pipe the data to the &lt;strong&gt;Select-Object&lt;/strong&gt; cmdlet and pick the last three entries in the data. The following script illustrates this technique (&lt;strong&gt;gps&lt;/strong&gt; is an alias for the &lt;strong&gt;Get-Process&lt;/strong&gt; cmdlet, and &lt;strong&gt;select&lt;/strong&gt; is an alias for the &lt;strong&gt;Select-Object&lt;/strong&gt; cmdlet).&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PS C:\&amp;gt; gps | select -Last 3&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Handles&amp;nbsp; NPM(K)&amp;nbsp;&amp;nbsp;&amp;nbsp; PM(K)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WS(K) VM(M)&amp;nbsp;&amp;nbsp; CPU(s)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Id ProcessName&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;-------&amp;nbsp; ------&amp;nbsp;&amp;nbsp;&amp;nbsp; -----&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ----- -----&amp;nbsp;&amp;nbsp; ------&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; -- -----------&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 207&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;9&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1340&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3064&amp;nbsp;&amp;nbsp;&amp;nbsp; 40&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1848 WUDFHost&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 405&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 19&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3636&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 10012&amp;nbsp;&amp;nbsp;&amp;nbsp; 95&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1904 WUDFHost&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 214&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 18&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3336&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 7852&amp;nbsp;&amp;nbsp;&amp;nbsp; 89&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2880 ZeroConfigService&lt;/p&gt;
&lt;p&gt;I use this type of code when I am troubleshooting or simply perusing the status of a computer. Because I have established a pattern that pipes data to the &lt;strong&gt;Select-Object&lt;/strong&gt; cmdlet and chooses the last three items, I can put this into a function that accepts pipelined input and outputs the last three items.&lt;/p&gt;
&lt;p&gt;Because I am writing the function interactively in the Windows PowerShell console, and because I will be using it a lot, I give it a really short name. Here I call it &amp;ldquo;&lt;strong&gt;l&lt;/strong&gt;&amp;rdquo; (as in lower case letter &amp;ldquo;L&amp;rdquo;). Inside the script block, I use the automatic variable &lt;strong&gt;$input&lt;/strong&gt;, which is the input piped into a function.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;$input&lt;/strong&gt; variable only exists inside the context of a function, and only for the time the function is called. If I check the value of &lt;strong&gt;$input&lt;/strong&gt; outside of the function, it is empty. So what I pass to the function is then piped to the &lt;strong&gt;Select-Object&lt;/strong&gt; cmdlet, and the last three items are returned from the function. The function is shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;function l {$input | select -Last 3}&lt;/p&gt;
&lt;p&gt;To use the function, I pipe results to the function. The following script selects the last three processes.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PS C:\&amp;gt; gps | l&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Handles&amp;nbsp; NPM(K)&amp;nbsp;&amp;nbsp;&amp;nbsp; PM(K)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WS(K) VM(M)&amp;nbsp;&amp;nbsp; CPU(s)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Id ProcessName&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;-------&amp;nbsp; ------&amp;nbsp;&amp;nbsp;&amp;nbsp; -----&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ----- -----&amp;nbsp;&amp;nbsp; ------&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; -- -----------&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 207&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 9&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1340&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3064&amp;nbsp;&amp;nbsp;&amp;nbsp; 40&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1848 WUDFHost&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 405&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 19&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3636&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 10012&amp;nbsp;&amp;nbsp;&amp;nbsp; 95&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1904 WUDFHost&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 214&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 18&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3336&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 7852&amp;nbsp;&amp;nbsp;&amp;nbsp; 89&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2880 ZeroConfigService&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:12px;"&gt;I can select the last three services (&lt;/span&gt;&lt;strong style="font-size:12px;"&gt;gsv&lt;/strong&gt;&lt;span style="font-size:12px;"&gt; is an alias) as shown here.&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;gsv | l&lt;/p&gt;
&lt;p&gt;Or maybe I want to look at the last three entries in the event log as shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-EventLog application | l&lt;/p&gt;
&lt;p&gt;I can even use the &lt;strong&gt;range&lt;/strong&gt; operator and select the last three numbers. This command is shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;1..10 | l&lt;/p&gt;
&lt;p&gt;These commands and their associated output are shown in the following image.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/5417.hsg_2D00_4_2D00_9_2D00_13_2D00_01.png"&gt;&lt;img style="border:0px currentColor;" title="Image of command output" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/5417.hsg_2D00_4_2D00_9_2D00_13_2D00_01.png" alt="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Best Practices Week will continue tomorrow when I will continue talking about functions.&lt;/p&gt;
&lt;p&gt;I invite you to follow me on &lt;a href="http://bit.ly/scriptingguystwitter" target="_blank"&gt;Twitter&lt;/a&gt; and &lt;a href="http://bit.ly/scriptingguysfacebook" target="_blank"&gt;Facebook&lt;/a&gt;. If you have any questions, send email to me at &lt;a href="mailto:scripter@microsoft.com" target="_blank"&gt;scripter@microsoft.com&lt;/a&gt;, or post your questions on the &lt;a href="http://bit.ly/scriptingforum" target="_blank"&gt;Official Scripting Guys Forum&lt;/a&gt;. See you tomorrow. Until then, peace.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ed Wilson, Microsoft Scripting Guy&lt;/strong&gt;&lt;span style="font-size:12px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3563607" width="1" height="1" alt="" /&gt;</description></item><item><title>Using PowerShell Aliases: Best Practices</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2013/04/08/using-powershell-aliases-best-practices.aspx</link><pubDate>Mon, 08 Apr 2013 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:22609</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;strong style="font-size:12px;"&gt;Summary&lt;/strong&gt;&lt;span style="font-size:12px;"&gt;: Microsoft Scripting Guy, Ed Wilson, demystifies some of the confusion surrounding using Windows PowerShell aliases.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. &amp;ldquo;Don&amp;rsquo;t use aliases!&amp;rdquo; I hear this all the time from various people on the Internet. I am constantly asked at Windows PowerShell user groups, at TechEd, and at community events such as Windows PowerShell Saturday, if it is alright to use an alias.&lt;/p&gt;
&lt;h2&gt;What&amp;rsquo;s the big deal anyway?&lt;/h2&gt;
&lt;p&gt;An alias is a shortcut name, or a nickname, for a Windows PowerShell cmdlet. It enables me to type a short name instead of a long name. Is this a big deal? You bet it is. Windows PowerShell ships with around 150 predefined aliases. The longest cmdlet name is 30 characters long. Yes, that is right&amp;mdash;30 characters. This is a very long command name. If I have to type &lt;strong&gt;New-PSSessionConfigurationFile&lt;/strong&gt; very many times, I am definitely going to seek an alias. Luckily, &lt;strong&gt;npssc&lt;/strong&gt;&lt;em&gt; &lt;/em&gt;is available to do the job.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;strong&gt;Note&amp;nbsp;&amp;nbsp;&lt;/strong&gt;I used the following code to determine the length of cmdlet names and their associated aliases.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;gal | select definition, @{label=&amp;quot;length&amp;quot;; expression={$_.definition.length}} | sort length&lt;/p&gt;
&lt;h2&gt;What about tab expansion?&lt;/h2&gt;
&lt;p&gt;Tab expansion works to help to reduce the typing load when working with Windows PowerShell. One of the issues with tab expansion is that in Windows&amp;nbsp;8, there are over 2000 cmdlets and functions. Therefore, it takes more tabs to expand the correct cmdlet name. In the previous example, rather than having to type 30 characters to get access to the &lt;strong&gt;New-PSSessionConfigurationFile&lt;/strong&gt; cmdlet, I can type &lt;strong&gt;New-P&lt;/strong&gt;&lt;em&gt; &lt;/em&gt;and hit the Tab key a few times. On my laptop, I have to press the Tab key four times before &lt;strong&gt;New-PSSessionConfigurationFile&lt;/strong&gt; appears on the command line.&lt;/p&gt;
&lt;p&gt;Typing five characters with &lt;strong&gt;New-P&lt;/strong&gt;&lt;em&gt; &lt;/em&gt;and pressing the Tab key four times is nine key strokes to enter the &lt;strong&gt;New-PSSessionConfigurationFile&lt;/strong&gt; command. The &lt;strong&gt;npssc&lt;/strong&gt;&lt;em&gt; &lt;/em&gt;alias is only five key strokes, so I save four key strokes every time I use the alias instead of using Tab expansion.&lt;/p&gt;
&lt;h2&gt;Use aliases when working interactively at the console&lt;/h2&gt;
&lt;p&gt;For me, it is a best practice to use Windows PowerShell aliases when I am working interactively in the Windows PowerShell console. This is because it is the best way to reduce the amount of typing. It also reduces the amount of memorization needed. For example, is it &lt;strong&gt;Get-ChildItem&lt;/strong&gt; or &lt;strong&gt;Get-ChildItems&lt;/strong&gt;? I do not need to remember either one, because I can use &lt;strong&gt;LS&lt;/strong&gt;, &lt;strong&gt;DIR&lt;/strong&gt;, or &lt;strong&gt;GCI&lt;/strong&gt; as an alias when calling that particular cmdlet.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;strong&gt;Note&lt;/strong&gt; &amp;nbsp;One of the most basic mistakes I see with beginners who are just learning Windows PowerShell is that they do not use Tab expansion, nor do they use aliases. Instead they attempt to type the entire Windows PowerShell cmdlet name&amp;mdash;and invariably, they get it wrong. So use aliases, or use tab expansion, but do not attempt to type the long cmdlet names.&lt;/p&gt;
&lt;p&gt;In addition, if there is a Windows PowerShell cmdlet that I use on a regular basis that does not have a currently defined alias, I like to create an alias and store it in my Windows PowerShell profile. In this way, I make sure I have easy access to any Windows PowerShell cmdlet regardless of the length of the actual cmdlet name.&lt;/p&gt;
&lt;h2&gt;When not to use aliases&lt;/h2&gt;
&lt;p&gt;With all the goodness that aliases bring to the table, I might be inclined to use aliases all the time. There is a disadvantage, however. Aliases can be hard to read. Some aliases make sense: &lt;strong&gt;Sort&lt;/strong&gt; for &lt;strong&gt;Sort-Object&lt;/strong&gt;, &lt;strong&gt;Where&lt;/strong&gt; for &lt;strong&gt;Where-Object&lt;/strong&gt;. Others, such as &lt;strong&gt;sv&lt;/strong&gt;, &lt;strong&gt;sbp&lt;/strong&gt;, &lt;strong&gt;sc&lt;/strong&gt;, and &lt;strong&gt;rv&lt;/strong&gt; are rather obscure. One of the nice things about Windows PowerShell code is that it is very readable. Therefore, &lt;strong&gt;Get-Service&lt;/strong&gt; does not need much explanation&amp;mdash;it returns service information. But &lt;strong&gt;gsv&lt;/strong&gt;, needs a bit of explanation before I know that it is an alias for &lt;strong&gt;Get-Service&lt;/strong&gt;. So, what I gain in speed of typing, I loose in ease of understanding.&lt;/p&gt;
&lt;p&gt;When working interactively at the Windows PowerShell console, the primary purpose is to accomplish something. I want to get the task completed accurately, and timely. I do not want to expend any extra effort to accomplish the task. When I close the Windows PowerShell console, everything I typed is lost (unless I have enabled the transcript or exported my command history).&lt;/p&gt;
&lt;p&gt;On the other hand, when I write a Windows PowerShell script, the purpose is to have something I can use over and over again. So I am creating an artifact that has intrinsic value, and that I can use as a management tool. The goal here is reusability, not speed of development and execution. Therefore, I do not want to use aliases in my script because it hinders readability and understanding.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;strong&gt;Note&amp;nbsp;&amp;nbsp;&lt;/strong&gt; A fundamental tenant of script development is that the better I can understand my script, the fewer errors it will contain, and the easier it will be to fix any errors that may arise. In addition, because scripts are reusable, it also will be easier to modify the script in the future. Time spent in script development is an investment in the future.&lt;/p&gt;
&lt;p&gt;This does not mean I have to give up the ease of using aliases when I am writing a Windows PowerShell script. I wrote a function that I include in my Windows PowerShell profile that replaces all aliases with the actual cmdlet name: &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2011/04/24/modify-the-powershell-ise-to-remove-aliases-from-scripts.aspx"&gt;Modify the PowerShell ISE to Remove Aliases from Scripts&lt;/a&gt;. In this way, I have the ease of being able to use Windows PowerShell aliases, with the readability of full cmdlet names later.&lt;/p&gt;
&lt;p&gt;Join me tomorrow when I will talk about more cool Windows PowerShell stuff.&lt;/p&gt;
&lt;p&gt;I invite you to follow me on &lt;a href="http://bit.ly/scriptingguystwitter" target="_blank"&gt;Twitter&lt;/a&gt; and &lt;a href="http://bit.ly/scriptingguysfacebook" target="_blank"&gt;Facebook&lt;/a&gt;. If you have any questions, send email to me at &lt;a href="mailto:scripter@microsoft.com" target="_blank"&gt;scripter@microsoft.com&lt;/a&gt;, or post your questions on the &lt;a href="http://bit.ly/scriptingforum" target="_blank"&gt;Official Scripting Guys Forum&lt;/a&gt;. See you tomorrow. Until then, peace.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ed Wilson, Microsoft Scripting Guy&lt;/strong&gt;&lt;span style="font-size:12px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3563600" width="1" height="1" alt="" /&gt;</description></item></channel></rss>