{"id":51723,"date":"2009-12-24T00:01:00","date_gmt":"2009-12-24T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2009\/12\/24\/hey-scripting-guy-can-windows-powershell-functions-accept-more-than-one-input\/"},"modified":"2009-12-24T00:01:00","modified_gmt":"2009-12-24T00:01:00","slug":"hey-scripting-guy-can-windows-powershell-functions-accept-more-than-one-input","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-can-windows-powershell-functions-accept-more-than-one-input\/","title":{"rendered":"Hey, Scripting Guy! Can Windows PowerShell Functions Accept More Than One Input?"},"content":{"rendered":"<p class=\"MsoNormal\">&nbsp;<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><\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p><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 have a function that I would like to modify to accept multiple inputs. I have seen examples of a function that uses a single input parameter, but I have not found a Windows PowerShell function that uses two inputs. How can I cause the function to accept two inputs? More importantly, how can I call a function that requires two inputs?<\/p>\n<p class=\"MsoNormal\"><span>&#8212; AR<\/span><\/p>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<\/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 AR, <\/p>\n<p class=\"MsoNormal\">Microsoft Scripting Guy Ed Wilson here. Back when I was playing in a rock band, I purchased a music synthesizer. It was an <a href=\"http:\/\/en.wikipedia.org\/wiki\/Synthesizer\"><font face=\"Segoe\">older synthesizer<\/font><\/a>, but was cool nonetheless. The only problem was that it allowed only one note at a time. While fun to play when first purchased, it quickly became boring. My creativity really needed more than one note to express itself. <\/p>\n<p class=\"MsoNormal\"><span>AR, I totally sympathize with your plight&mdash;to write really cool scripts you will at times need more than one input, just as I needed more than one note on my synthesizer. Luckily, you can easily add additional inputs to your functions.<\/span><span lang=\"PT\">&nbsp;<\/span><\/p>\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title=\"Image of Windows PowerShell 2.0 Best Practices book\" alt=\"Image of Windows PowerShell 2.0 Best Practices book\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/november\/hey1123\/hsg-11-23-09-03.jpg\" width=\"197\" height=\"240\"><\/p>\n<p class=\"Readeraidonly\">Note: Portions of today&#8217;s Hey, Scripting Guy! article are excerpted from the Microsoft Press book, <em>Windows PowerShell 2.0 Best Practices<\/em> by Ed Wilson. This book is <a title=\"now available\" href=\"http:\/\/bit.ly\/edwilsonbestpractices\">now available<\/a>.<\/p>\n<p class=\"MsoNormal\">To create a function that uses multiple input parameters, use the <b>Function<\/b> keyword, specify the name of the function, use variables for each input parameter, and then define the script block within the curly brackets. The pattern is seen here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">Function My-Function($Input1,$Input2)<br>{<br><span>&nbsp;<\/span>#Insert Code Here<br>}<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">An example of a function that takes multiple input parameters is the <b>Get-DiskSpace<\/b> function, which is seen in the Get-DiskSpace.ps1 script. <\/p>\n<p class=\"CodeBlockScreenedHead\"><b>Get-DiskSpace.ps1<\/p>\n<p><\/b><\/p>\n<p class=\"CodeBlock\"><span><br><font face=\"Lucida Sans Typewriter\">Function Get-DiskSpace($drive,$computer)<br>{<br><span>&nbsp;<\/span>([wmi]&#8221;\\$computerrootcimv2:Win32_logicalDisk.DeviceID=&#8217;$drive'&#8221;).FreeSpace<br>}<br>Get-DiskSpace -drive &#8220;C:&#8221; -computer &#8220;win7-pc&#8221;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">The Get-DiskSpace.ps1 script begins with the <b>Function<\/b> keyword, the name of the function, and the two input parameters. The input parameters are placed inside parentheses, as seen here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">Function Get-DiskSpace($drive,$computer)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">Inside the curly brackets, the <b>Get-DiskSpace<\/b> function uses the WMI <b>class<\/b> accelerator to query the <b>Win32_LogicalDisk<\/b> WMI class. It connects to the computer specified in the <b>$computer<\/b> parameter and filters out only the drive that is specified in the <b>$drive<\/b> parameter. When the function is called, each parameter is specified as <b>&ndash;drive<\/b> and <b>&ndash;computer<\/b>. In the function definition, the variables <b>$drive<\/b> and <b>$computer<\/b> are used to hold the values supplied to the parameters. <\/p>\n<p class=\"MsoNormal\">After the data from WMI is retrieved, it is stored in the <b>$driveData<\/b> variable. The data that is stored in the <b>$driveData<\/b> variable is an instance of the <b>Win32_LogicalDisk<\/b>. This variable contains a complete instance of the class. When the Get-DiskSpace.ps1 script runs, the following output is seen:<\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title=\"Image of output of script\" alt=\"Image of output of script\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/december\/hey1224\/hsg-12-24-09-01.jpg\" width=\"600\" height=\"420\"><\/p>\n<p class=\"Fig-Graphic\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\">When accepting parameters for a function, it may be important to use a <b>type<\/b> constraint to ensure the function receives the correct type of data. To do this, you place the desired <b>type<\/b> alias inside square brackets in front of the input parameter. This will constrain the data type, and prevent the entry of an incorrect type of data. Allowable <b>type<\/b> shortcuts are seen in Table 1.<\/p>\n<p class=\"TableNum-Title\"><strong>Table 1<span>&emsp;<\/span>Data Type Aliases<\/strong><\/p>\n<p class=\"MsoNormal\">\n<table class=\"MsoNormalTable\" border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"276\">\n<p class=\"TableHead\"><strong>Alias<\/p>\n<p><\/strong><\/p>\n<\/td>\n<td valign=\"top\" width=\"283\">\n<p class=\"TableHead\"><b>Type<\/p>\n<p><\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"276\">\n<p class=\"TableText\">[int]<\/p>\n<\/td>\n<td valign=\"top\" width=\"283\">\n<p class=\"TableText\">32-bit signed integer<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"276\">\n<p class=\"TableText\">[long]<\/p>\n<\/td>\n<td valign=\"top\" width=\"283\">\n<p class=\"TableText\">64-bit signed integer<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"276\">\n<p class=\"TableText\">[string]<\/p>\n<\/td>\n<td valign=\"top\" width=\"283\">\n<p class=\"TableText\">Fixed length string of Unicode characters<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"276\">\n<p class=\"TableText\">[char]<\/p>\n<\/td>\n<td valign=\"top\" width=\"283\">\n<p class=\"TableText\">A Unicode 16-bit character <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"276\">\n<p class=\"TableText\">[bool]<\/p>\n<\/td>\n<td valign=\"top\" width=\"283\">\n<p class=\"TableText\">True\/False value<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"276\">\n<p class=\"TableText\">[byte]<\/p>\n<\/td>\n<td valign=\"top\" width=\"283\">\n<p class=\"TableText\">An 8-bit unsigned integer<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"276\">\n<p class=\"TableText\">[double]<\/p>\n<\/td>\n<td valign=\"top\" width=\"283\">\n<p class=\"TableText\">Double-precision 64-bit floating point number<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"276\">\n<p class=\"TableText\">[decimal]<\/p>\n<\/td>\n<td valign=\"top\" width=\"283\">\n<p class=\"TableText\">A 128-bit decimal value<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"276\">\n<p class=\"TableText\">[single]<\/p>\n<\/td>\n<td valign=\"top\" width=\"283\">\n<p class=\"TableText\">Single precision 32-bit floating point number<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"276\">\n<p class=\"TableText\">[array]<\/p>\n<\/td>\n<td valign=\"top\" width=\"283\">\n<p class=\"TableText\">An array of values<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"276\">\n<p class=\"TableText\">[xml]<\/p>\n<\/td>\n<td valign=\"top\" width=\"283\">\n<p class=\"TableText\">XML objects<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"276\">\n<p class=\"TableText\">[hashtable]<\/p>\n<\/td>\n<td valign=\"top\" width=\"283\">\n<p class=\"TableText\">A <b>hashtable<\/b> object (similar to a <b>dictionary<\/b> object)<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\">In the <b>Resolve-ZipCode<\/b> function, which is seen in the Resolve-ZipCode.ps1 script, the <b>$zip<\/b> input parameter is constrained to only allow a 32-bit signed integer for input. Obviously, the <b>[int]<\/b> type constraint would eliminate most of the world&#8217;s ZIP and postal codes, but the Web service the script uses only resolves US based ZIP codes, so it is a good addition to the function.<\/p>\n<p class=\"MsoNormal\">In the <b>Resolve-ZipCode<\/b> function, the first thing that is done is to use a string that points to the WSDL for the Web service. Next, the <b>New-WebServiceProxy<\/b> cmdlet is used to create a new <b>webservice<\/b> proxy for the <b>ZipCode<\/b> service. The WSDL for the <b>ZipCode<\/b> service defines a method called the <b>GetInfoByZip<\/b> method. It will accept a standard United States&ndash;based zipcode. The results are displayed as a table. The Resolve-ZipCode.ps1 script is seen here. <\/p>\n<p class=\"CodeBlockScreenedHead\"><b>Resolve-ZipCode.ps1<\/p>\n<p><\/b><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">#Requires -Version 2.0<br>Function Resolve-ZipCode([int]$zip)<br>{<br><span>&nbsp;<\/span>$URI = &#8220;http:\/\/www.webservicex.net\/uszip.asmx?WSDL&#8221;<br><span>&nbsp;<\/span>$zipProxy = New-WebServiceProxy -uri $URI -namespace WebServiceProxy -class ZipClass<br><span>&nbsp;<\/span>$zipProxy.getinfobyzip($zip).table<br>} #end Get-ZipCode<\/p>\n<p>Resolve-ZipCode 28273<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\">When the Resolve-ZipCode.ps1 script runs, the following output is displayed:<\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title=\"Image of output of script\" alt=\"Image of output of script\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/december\/hey1224\/hsg-12-24-09-02.jpg\" width=\"600\" height=\"462\"><\/p>\n<p class=\"Fig-Graphic\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\">When using a type constraint on an input parameter, any deviation from the expected data type will generate an error similar to the one seen here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">Resolve-ZipCode : Cannot process argument transformation on parameter &#8216;zip&#8217;. Cannot convert value &#8220;COW&#8221; to type &#8220;System<br>.Int32&#8243;. Error: &#8220;Input string was not in a correct format.&#8221;<br>At C:Usersedwils.NORTHAMERICAAppDataLocalTemptmp3351.tmp.ps1:22 char:16<br>+ Resolve-ZipCode &lt;&lt;&lt;&lt;<span>&nbsp; <\/span>&#8220;COW&#8221;<br><span>&nbsp;&nbsp;&nbsp; <\/span>+ CategoryInfo<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>: InvalidData: (:) [Resolve-ZipCode], ParameterBindin&#8230;mationException<br><span>&nbsp;&nbsp;&nbsp; <\/span>+ FullyQualifiedErrorId : ParameterArgumentTransformationError,Resolve-ZipCode<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">Needless to say, such an error could be distracting to the users of the function. One way to handle the problem of confusing error messages is to use the <b>Trap<\/b> keyword. In the DemoTrapSystemException.ps1 script, the <b>My-Test<\/b> function uses <b>[int]<\/b> to constrain the <b>$myinput<\/b> variable to accept only a 32-bit unsigned integer for input. If such an integer is received by the function when it is called, the function will return the string &#8220;It worked.&#8221; If the function receives a string for input, an error will be raised, similar to the one seen above. <\/p>\n<p class=\"MsoNormal\">Rather than displaying a raw error message, which most users and many IT pros find confusing, it is a best practice to suppress the display of the error message, and perhaps inform the user that an error condition has occurred, and provide more meaningful and direct information that the user can then relay to the help desk. Many times, IT departments will display such an error message, complete with either a local telephone number for the appropriate help desk or even a link to an internal Web page that provides detailed troubleshooting and self-help corrective steps the user can perform. You could even provide a Web page that hosted a script the user could run that would fix the problem. This is similar to the <a href=\"http:\/\/support.microsoft.com\/fixit\"><span><font face=\"Segoe\">Fix it<\/font><\/span><\/a> Web pages Microsoft introduced. <\/p>\n<p class=\"MsoNormal\">When an instance of a <b>System.SystemException<\/b> class is created when a system exception occurs, the <b>Trap<\/b> statement will trap the error, rather than allowing it to display the error information on the screen. If you were to query the <b>$error<\/b> variable, you would see that the error had in fact occurred and was actually received by the error record. You would also have access to the <b>ErrorRecord<\/b> class via the <b>$_<\/b> automatic variable, which means the error record has been passed along the pipeline. This gives you the ability to build a rich error-handling solution. In this example, the string &#8220;error trapped&#8221; is displayed, and the <b>Continue<\/b> statement is used to continue the script execution on the next line of code. In this example, the next line of code that is executed is the &#8220;After the error&#8221; string. When the DemoTrapSystemException.ps1 script is run, the following output is seen:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">error trapped<br>After the error<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">The complete DemoTrapSystemException.ps1 script is shown here. <\/p>\n<p class=\"CodeBlockScreenedHead\"><b>DemoTrapSystemException.ps1<\/p>\n<p><\/b><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">Function My-Test([int]$myinput)<br>{<br><span>&nbsp;<\/span><br><span>&nbsp;<\/span>&#8220;It worked&#8221;<br>} #End my-test function<br># *** Entry Point to Script ***<\/p>\n<p>Trap [SystemException] { &#8220;error trapped&#8221; ; continue }<br>My-Test -myinput &#8220;string&#8221;<br>&#8220;After the error&#8221;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\">AR that is all there is to using multiple inputs for your functions. That also wraps up Function Week. Join us tomorrow on Christmas Day for Quick-Hits Friday!<\/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 your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.<\/p>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<\/p>\n<p><b><span>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/p>\n<p><\/span><\/b><\/p>\n<p class=\"MsoNormal\"><b><span><\/span><\/b>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp; &nbsp; Hey, Scripting Guy! I have a function that I would like to modify to accept multiple inputs. I have seen examples of a function that uses a single input parameter, but I have not found a Windows PowerShell function that uses two inputs. How can I cause the function to accept two inputs? [&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-51723","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; &nbsp; Hey, Scripting Guy! I have a function that I would like to modify to accept multiple inputs. I have seen examples of a function that uses a single input parameter, but I have not found a Windows PowerShell function that uses two inputs. How can I cause the function to accept two inputs? [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/51723","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=51723"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/51723\/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=51723"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=51723"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=51723"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}