{"id":52053,"date":"2009-11-10T00:01:00","date_gmt":"2009-11-10T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2009\/11\/10\/hey-scripting-guy-how-can-i-create-a-custom-function\/"},"modified":"2009-11-10T00:01:00","modified_gmt":"2009-11-10T00:01:00","slug":"hey-scripting-guy-how-can-i-create-a-custom-function","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-create-a-custom-function\/","title":{"rendered":"Hey, Scripting Guy! How Can I Create a Custom Function?"},"content":{"rendered":"<p><!-- AddThis Button BEGIN --><a class=\"addthis_button\" href=\"http:\/\/www.addthis.com\/bookmark.php?v=250&amp;pub=scriptingguys\"><img decoding=\"async\" alt=\"Bookmark and Share\" src=\"http:\/\/s7.addthis.com\/static\/btn\/v2\/lg-share-en.gif\" width=\"125\" height=\"16\"><\/a><!-- AddThis Button END --><\/p>\n<p class=\"MsoNormal\"><b><\/p>\n<p><\/b>&nbsp;<\/p>\n<p class=\"Readeraidonly\"><img decoding=\"async\" title=\"Hey, Scripting Guy! Question\" border=\"0\" alt=\"Hey, Scripting Guy! Question\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" height=\"34\"><\/p>\n<p class=\"MsoNormal\">Hey, Scripting Guy! I am getting tired of typing the long commands used in Windows PowerShell. I know you Scripting Guys seem to show people always typing commands inside the Windows PowerShell console, but I do not think I like to work that way. It is TOO MUCH TYPING. I would love to be able to shorten some of the commands, but I do not think that is possible. <\/p>\n<p class=\"MsoNormal\">&#8212; DR<\/p>\n<p class=\"MsoNormal\"><img decoding=\"async\" title=\"Hey, Scripting Guy! Answer\" border=\"0\" alt=\"Hey, Scripting Guy! Answer\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" height=\"34\">Hello DR, <\/p>\n<p class=\"MsoNormal\">Microsoft Scripting Guy Ed Wilson here, it is a cold day in Charlotte, North Carolina, in the United States. The sky is clear, and the sun is shining, but it&rsquo;s an autumn sun and is not doing that much good. I even saw some people wearing jackets outside. For the sunny south, 50 degrees Fahrenheit (10 degrees Celsius) is enough to drive the children inside and bring the big wooly mothball-smelling coats outside. I am sipping a cup of aged Earl Gray tea with a cinnamon stick and a dash of warm milk to smooth the flavor. Along with the tea, I have a slice of Fuji apple and Wisconsin sharp cheddar cheese. It is a departure from my normal afternoon snack, but the combination seems to work well with autumn. The neighborhood Halloween decorations persist in some yards of overzealous homeowners in the subdivision, but that has not stopped others from putting out giant blow-up turkeys in anticipation of Thanksgiving. Yet with all that going on outside, the stores are skipping past Thanksgiving in hopes that St. Nick will soon be there. It is a confusing time. Therefore, a confused snack. <\/p>\n<p class=\"MsoNormal\">DR, I am not confused by your request. I have felt the same way myself. What I generally do is create a custom function that does what I want, and then create an alias for the function. I then add these items to my Windows PowerShell profile. Let&rsquo;s begin by looking at creating a custom function. <\/p>\n<p class=\"Readeraidonly\">Note: Portions of today&#8217;s Hey, Scripting Guy! post are excerpted from the Microsoft Press book, <i>Windows PowerShell 2.0 Best Practices<\/i> by Ed Wilson. The book is <a href=\"http:\/\/bit.ly\/edwilsonbestpractices\"><font face=\"Segoe\">available for pre-order<\/font><\/a>. <\/p>\n<p class=\"MsoNormal\">Functions provide a nearly endless capability of customization from within Windows PowerShell. The profile is a great place to supply some of this customization. As an example, suppose that when using the <b>Get-Help<\/b> cmdlet you prefer to see the full article, but you also know that in most cases the article is too long to fit on a single screen; therefore, you pipeline the output to the <b>more<\/b> function, which provides paging control. If you were looking for information about the <b>Get-Process<\/b> cmdlet, the command would be the one shown here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">Get-Help Get-Process -Full | more<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">There is nothing wrong with typing the above command except that, even when paired with tab expansion, it is more than 30 keystrokes. It does not take very long before you get tired of typing such a command. This is a perfect candidate for a function. When naming functions, it is a best practice to use the Verb-Noun naming convention because this syntax will be familiar to users of Windows PowerShell, and you can take advantage of tab expansion. As seen here, I named our function <b>Get-MoreHelp<\/b>. <\/p>\n<p class=\"CodeBlockScreenedHead\"><strong>Get-MoreHelp.ps1<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/strong><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">Function Get-MoreHelp()<br>{<br><span>&nbsp;<\/span>Get-Help $args[0] -Full | <br><span>&nbsp;<\/span>more<br>} #end Get-MoreHelp<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">The <b>Get-MoreHelp<\/b> function begins by using the <b>Function<\/b> keyword to declare the function. After the <b>Function<\/b> keyword, we specify the name of the function, which in this example is <b>Get-MoreHelp<\/b>. The empty parentheses are not required after the function name. The parentheses would be used to define parameters, and without any parameters, the parenthesis are not required. I generally include them as an indicator that a parameter could be specified in the position. This is seen here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">Function Get-MoreHelp()<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">Following the <b>Function<\/b> keyword, the function opens the code block by using an opening curly bracket. When typing the function I always open the code block with one curly bracket, and immediately on the next line type the closing curly bracket. In this way, I never forget to close a code block. As a best practice, I always include a comment that indicates the bottom curly bracket closes the function. The end comments also are a tremendous help when it comes time to troubleshoot the script because they promote readability and make it easier to understand the delimiters of the function. In addition, if you have a long function that scrolls off the screen, the end comment, with its repetition of the function name, makes it easier to create the alias for the function as well. This is seen here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">{<\/p>\n<p>} #end Get-MoreHelp<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">The <b>Get-MoreHelp<\/b> function uses the <b>$args<\/b> automatic variable to hold the argument that was passed to the function when it is called. Because the <b>Get-Help<\/b> cmdlet does not accept an array for the name parameter, we use <b>[0]<\/b> to index into the first element of the <b>$args<\/b> array. If, as is required, there is only one item passed to the function, the item will always be element 0 of the array. The function passes the <b>&ndash;full<\/b> switched parameter to the <b>Get-Help<\/b> cmdlet. The resulting help information is passed along the pipeline via the pipe (&ldquo;<b>|<\/b>&rdquo;) symbol. This is shown here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">Get-Help $args[0] -full |<\/p>\n<p><\/font><\/span><\/p>\n<h3><font size=\"3\"><br>Overriding existing commands<\/font><\/h3>\n<p class=\"MsoNormal\">Because it is possible for the <b>Get-MoreHelp<\/b> function to return more than a single screen of textual information, the function pipes the help information to the <b>more<\/b> function. Functions are first-class citizens in Windows PowerShell, and they have priority over executables and even native Windows PowerShell cmdlets. Because of this, it is easy to modify the behavior of an executable or cmdlet by creating a function with the same name as an existing one. This is illustrated by the <b>more<\/b> function. <b>More.com<\/b> is an executable that provides the ability to return information to the screen one page at a time&mdash;it has been available since the DOS days. The <b>more<\/b> function is used to modify the behavior of <b>more.com<\/b>. The content of the <b>more<\/b> function is shown here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">param([string[]]$paths)<br>if($paths)<br>{<br><span>&nbsp;&nbsp;&nbsp; <\/span>foreach ($file in $paths)<br><span>&nbsp;&nbsp;&nbsp; <\/span>{<br><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Get-Content $file | more.com<br><span>&nbsp;&nbsp;&nbsp; <\/span>}<br>}<br>else<br>{<br><span>&nbsp;&nbsp;&nbsp; <\/span>$input | more.com<br>}<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">By looking at the content of the <b>More<\/b> function, we see that there has been a useful addition to the functionality of <b>more.com<\/b>. If you supply a path to the <b>More<\/b> function, it will retrieve the content of the file and pipe the result to the <b>more.com<\/b> executable. This is shown here:<\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title=\"Image of supplying a path to the More function\" alt=\"Image of supplying a path to the More function\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/november\/hey1110\/hsg-11-10-09-1.jpg\" width=\"600\" height=\"429\"><a href=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/november\/hey1110\/hsg-11-10-09-1.jpg\"><\/a><\/p>\n<h3><font size=\"3\"><br>Alias the function<\/font><\/h3>\n<p class=\"MsoNormal\">When I create utility functions, I generally like to create an alias for the function. This will enable quick and easy access to the function. It is possible to create the function and the alias in the same script, but not within the function definition. The problem is that within the function definition, the function has not yet been created and therefore you cannot create an alias for a function that does not yet exist. But there is nothing wrong with creating the alias and the function in the same script. Interestingly enough, you can create the alias on a line before the function is declared or after the function is declared. Position does not matter. <\/p>\n<p class=\"CodeBlockScreenedHead\"><strong>Get-MoreHelpWithAlias.ps1<\/strong><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">Function Get-MoreHelp()<br>{<br><span>&nbsp;<\/span>Get-Help $args[0] -full | <br><span>&nbsp;<\/span>more<br>} #End Get-MoreHelp<br>New-Alias -name gmh -value Get-MoreHelp -Option allscope<\/p>\n<p><\/font><\/span><\/p>\n<h3><font size=\"3\"><br>Loop the array<\/font><\/h3>\n<p class=\"MsoNormal\">The <b>$args<\/b> variable returns an array; we can use this to our advantage and add the ability to pass two or more pieces of information and receive help for each topic. To do this, we use the <b>For<\/b> statement to loop through the elements of <b>$args<\/b>. The <b>For<\/b> statement uses three parameters: the beginning, the destination, and the method of travel. In this example, the variable <b>$i<\/b> is used to keep track of the position within the array. The variable <b>$i<\/b> is set equal to 0, and the <b>&ndash;le<\/b> operator (less than or equal to) is used to allow the loop to continue for the number of times that is represented by the count of the number of items in <b>$args<\/b>. As the loop progresses, the value of <b>$i<\/b> is incremented by one each time through the loop. The <b>$i++<\/b> construction does this. This line of code is seen here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">For($i = 0 ;$i -le $args.count ; $i++)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">One small change is required to the line of code that calls the <b>Get-Help<\/b> cmdlet. Instead of using <b>$args[0]<\/b>, which will always retrieve the first element in the array, we change the <b>0<\/b> to <b>$i<\/b>. As the value of <b>$i<\/b> increases for each loop, the <b>Get-Help<\/b> cmdlet will query the next item in the array. This modified line of code is seen here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">Get-Help $args[$i] -full |<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">The remainder of the <b>Get-MoreHelp<\/b> function is the same as previous versions, which were discussed earlier. The complete function is seen in the Get-MoreHelp2.ps1 script. <\/p>\n<p class=\"CodeBlockScreenedHead\"><strong>Get-MoreHelp2.ps1<\/strong><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">Function Get-MoreHelp<br>{<br><span>&nbsp;<\/span># .help Get-MoreHelp Get-Command Get-Process<br><span>&nbsp;<\/span>For($i = 0 ;$i -le $args.count ; $i++)<br><span>&nbsp;<\/span>{<br><span>&nbsp; <\/span>Get-Help $args[$i] -full |<br><span>&nbsp; <\/span>more<br><span>&nbsp;<\/span>} #end for<br>} #end Get-MoreHelp<br>New-Alias -name gmh -value Get-MoreHelp -Option allscope<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">To run the <b>Get-MoreHelp<\/b> function, you can use the alias <b>gmh<\/b> and supply it one or more cmdlet names to get the help. This is seen in the following image where the function code was typed directly into the Windows PowerShell console:<\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title=\"Image of using the gmh alias\" alt=\"Image of using the gmh alias\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/november\/hey1110\/hsg-11-10-09-2.jpg\" width=\"600\" height=\"422\"><a href=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/november\/hey1110\/hsg-11-10-09-2.jpg\"><span><font face=\"Segoe\"><\/font><\/span><\/a><\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\">Well, DR, this should get you started on creating custom functions and aliases. Join us tomorrow as we continue examining ways to customize our Windows PowerShell environment. <\/p>\n<p class=\"MsoNormal\">If you want to know exactly what we will be looking at tomorrow, follow us on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a> or <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\">Facebook<\/a>. If you have any questions, send e-mail to us at <a href=\"http:\/\/blogs.technet.commailto:scripter@microsoft.com\" target=\"_blank\"><font face=\"Segoe\">scripter@microsoft.com<\/font><\/a> or post them on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, keep on scripting!<\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p><b><span>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/span><\/b><\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp; Hey, Scripting Guy! I am getting tired of typing the long commands used in Windows PowerShell. I know you Scripting Guys seem to show people always typing commands inside the Windows PowerShell console, but I do not think I like to work that way. It is TOO MUCH TYPING. I would love to be [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[51,3,45],"class_list":["post-52053","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-getting-started","tag-scripting-guy","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>&nbsp; Hey, Scripting Guy! I am getting tired of typing the long commands used in Windows PowerShell. I know you Scripting Guys seem to show people always typing commands inside the Windows PowerShell console, but I do not think I like to work that way. It is TOO MUCH TYPING. I would love to be [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/52053","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=52053"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/52053\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=52053"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=52053"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=52053"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}