{"id":53063,"date":"2009-06-30T03:01:00","date_gmt":"2009-06-30T03:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2009\/06\/30\/hey-scripting-guy-how-can-i-supply-more-than-one-value-from-the-command-line\/"},"modified":"2009-06-30T03:01:00","modified_gmt":"2009-06-30T03:01:00","slug":"hey-scripting-guy-how-can-i-supply-more-than-one-value-from-the-command-line","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-supply-more-than-one-value-from-the-command-line\/","title":{"rendered":"Hey, Scripting Guy! How Can I Supply More Than One Value from the Command Line?"},"content":{"rendered":"<h2><img decoding=\"async\" class=\"nearGraphic\" 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\"> Hey, Scripting Guy! <span><span>I do not think I write very complicated scripts, but quite often I find that it would be nice to be able to supply more than one value from the command line. It seems that everything I see written for Windows PowerShell uses the <strong>$args<\/strong> variable to get command line input, and I cannot figure out how to make <strong>$args<\/strong> accept more than one value. Can you help me? I looked over all the submissions I saw for the 2009 Summer Scripting Games, and I did not see anything there either.<\/span> <br><\/span><br>&#8211; KA<\/p>\n<p><img decoding=\"async\" border=\"0\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" height=\"5\"><img decoding=\"async\" class=\"nearGraphic\" 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\"><\/p>\n<p>Hi KA,<\/p>\n<p><span><span>Your question reminds me of a time when I was scuba diving off the coast of the Big Island, in the state of Hawaii in the United States. It was a beautiful spring day, with high-level puffy white clouds and a sea state that is best described as glass. From the deck of side of the dive boat, I could look down and see the rock formations 100 feet below the surface of the boat. Schools of <span><a href=\"http:\/\/en.wikipedia.org\/wiki\/Humuhumunukunukuapuaa\"><font color=\"#0000ff\" face=\"Segoe\">humuhumunukunukuapuaa<\/font><\/a><\/span> were swimming around looking for food or scuba divers to harass. (The humuhumunukunukuapuaa is a brightly colored reef trigger fish. By the way, if you ever get a scuba certification in Hawaii, you have to be able to pronounce the name of that fish.) The water was a warm 82 degrees. The highlight of the dive was a 40-foot-long lava tube, which was about as wide as an elevator. After doing a rolling entry into the water and joining my dive buddy, we headed over to the entrance to the lava tube and began our descent. The further down we went, the darker the inside of the lava tube became. After one rather narrow passage, we came upon a shelf, and lying there was this shark:<\/span><\/span><\/p>\n<p><span><span><\/span><img decoding=\"async\" title=\"Image of a shark\" alt=\"Image of a shark\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/june\/hey0630\/hsg-06-30-09-01.jpg\" width=\"600\" height=\"373\">&nbsp;<\/span><\/p>\n<p><span>  <\/p>\n<p class=\"MsoNormal\">When your flashlight uncovers a smiling nine-foot shark inside a darkened space about the size of an elevator<span>&mdash;<\/span>let&#8217;s just say that you begin to have multiple sources of input. <\/p>\n<p class=\"MsoNormal\">KA, handling multiple input parameters from the command line of your script will not require you to wrestle elevator sharks. But if you need to supply multiple values via the command line, and you attempt to do so via the <b>$args<\/b> automatic variable, you will be greeted with the following error message that warns of a type mismatch. The error does not use the term &ldquo;type mismatch,&rdquo; but this is what is meant by the error. It states you are attempting to supply an object array to a string. The <b>computername<\/b> parameter, it states, requires a string for its input:<\/p>\n<p><span><font size=\"1\"><font><font face=\"Lucida Sans Typewriter\">Get-WmiObject : Cannot convert &#8216;System.Object[]&#8217; to the type &#8216;System.String&#8217; required by parameter &#8216;ComputerName&#8217;. Specified method is not supported.<br>At C:Usersedwils.NORTHAMERICAAppDataLocalTemptmp774.tmp.ps1:18 char:47<br>+<span>&nbsp; <\/span>Get-WmiObject -Class win32_bios -computername &lt;&lt;&lt;&lt;<span>&nbsp; <\/span>$args<br><span>&nbsp;&nbsp;&nbsp; <\/span>+ CategoryInfo<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>: InvalidArgument: (:) [Get-WmiObject], ParameterBindingException<br><span>&nbsp;&nbsp;&nbsp; <\/span>+ FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.GetWmiObjectCommand<\/font><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\">The error is not caused by the array. The error is caused because the <b>$args<\/b> automatic variable arrives as a <b>System.Object<\/b> array. The <b>Get-WmiObject<\/b> cmdlet will accept an array of computer names to the <b>computername<\/b> parameter. This is seen here where an array of computer names is supplied directly to the <b>computername<\/b><i> <\/i>parameter and BIOS information is retrieved via the <b>WIN32_Bios<\/b> WMI class. <\/p>\n<p><span><font size=\"1\"><font><font face=\"Lucida Sans Typewriter\">PS C:&gt; Get-WmiObject -Class Win32_Bios -ComputerName localhost,loopback<\/p>\n<p><br>SMBIOSBIOSVersion : 7LETB7WW (2.17 )<br>Manufacturer<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>: LENOVO<br>Name<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>: Ver 1.00PARTTBLx<br>SerialNumber<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>: L3L4518<br>Version<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>: LENOVO &#8211; 2170<\/p>\n<p>SMBIOSBIOSVersion : 7LETB7WW (2.17 )<br>Manufacturer<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>: LENOVO<br>Name<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>: Ver 1.00PARTTBLx<br>SerialNumber<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>: L3L4518<br>Version<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>: LENOVO &#8211; 2170<\/font><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><br>There are a couple of ways to solve this issue. The first way is to index into the array and force the retrieval of the computer names. This is shown in the Get-BiosArray1.ps1 script:<\/p>\n<p class=\"MsoNormal\"><b>Get-BiosArray1.ps1<\/p>\n<p><\/b><\/p>\n<p><span><font size=\"1\"><font><font face=\"Lucida Sans Typewriter\">Get-WmiObject -Class win32_bios -computername $args[0]<\/font><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><br>The technique of indexing directly into the <b>$args<\/b> automatic variable works well. The problem is it looks like it would only retrieve the first item in the array, but it in fact retrieves both items. Because Windows PowerShell automatically handles the transition between a single item and multiple items in an array, the technique of indexing into element 0 of the array works whether one or more items are supplied. This issue of the way the Windows PowerShell <b>$args<\/b> automatic variable handles an array of information can be seen in the StringArgs.ps1 script:<\/p>\n<p class=\"MsoNormal\"><b>StringArgs.ps1<\/p>\n<p><\/b><\/p>\n<p><span><font size=\"1\"><font><font face=\"Lucida Sans Typewriter\">&#8216;The value of arg0 &#8216; + $args[0] + &#8216; the value of arg1 &#8216; + $args[1]<\/font><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><br>When the StringArgs1.ps1 script is run with the array <b>&#8220;string1&#8243;,&#8221;String2&#8221;<\/b> supplied from the command line, the entire array is displayed in <b>$args[0]<\/b> and nothing is displayed for <b>$args[1]<\/b>. This is shown here: <\/p>\n<p><span><font size=\"1\"><font><font face=\"Lucida Sans Typewriter\">PS C:&gt; StingArgs.ps1 &#8220;string1&#8243;,&#8221;String2&#8221;<br>The value of arg0 string1 String2 the value of arg1<br>PS C:&gt;<\/font><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><br>A better way to handle an array that is supplied to the <b>$args<\/b> automatic variable is to use the <b>ForEach-Object<\/b> cmdlet and pipeline the array to the <b>Get-WmiObject<\/b> cmdlet. This is seen in Get-BiosArray2.ps1:<\/p>\n<p class=\"MsoNormal\"><b>Get-BiosArray2.ps1<\/p>\n<p><\/b><\/p>\n<p><span><font size=\"1\"><font><font face=\"Lucida Sans Typewriter\">$args | Foreach-Object {<br>Get-WmiObject -Class win32_bios -computername $_<br>}<span>&nbsp; <\/span><\/font><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\">When the Get-BiosArray2.ps1 script is started with an array of computer names from the Windows PowerShell prompt, the following output is displayed:<\/p>\n<p><span><font size=\"1\"><font><font face=\"Lucida Sans Typewriter\">PS C:&gt; Get-BiosArray2.ps1 localhost,loopback<br>SMBIOSBIOSVersion : 7LETB7WW (2.17 )<br>Manufacturer<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>: LENOVO<br>Name<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>: Ver 1.00PARTTBLx<br>SerialNumber<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>: L3L4518<br>Version<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>: LENOVO &#8211; 2170<\/p>\n<p>SMBIOSBIOSVersion : 7LETB7WW (2.17 )<br>Manufacturer<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>: LENOVO<br>Name<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>: Ver 1.00PARTTBLx<br>SerialNumber<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>: L3L4518<br>Version<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>: LENOVO &ndash; 2170<\/font><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><br>There are two advantages to using the <b>ForEach-Object<\/b> cmdlet. The first is readability of the code. It meets the principle of &ldquo;least shock.&rdquo; When someone reads the code and they see that the script accepts an array for input via the <b>$args<\/b> variable, they are not surprised when they see the script using the <b>ForEach-Object<\/b> cmdlet to walk through the array. The other advantage is that the script will work when a single value is supplied for the input. <\/p>\n<p class=\"MsoNormal\">Unfortunately, if the same approach is tried with the StringArgsArray.ps1 script, the value of the <b>$args<\/b> array is repeated twice. The StringArgsArray1.ps1 script is seen here: <\/p>\n<p class=\"MsoNormal\"><b>StringArgsArray1.ps1<\/p>\n<p><\/b><\/p>\n<p><span><font size=\"1\"><font><font face=\"Lucida Sans Typewriter\">$args | ForEach-Object {<br>&#8216;The value of arg0 &#8216; + $_ + &#8216; the value of arg1 &#8216; + $_ <br>}<\/font><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><br>When the StringArgsArray1.ps1 script is started, the results seen here are displayed: <\/p>\n<p><span><font size=\"1\"><font><font face=\"Lucida Sans Typewriter\">PS C:&gt; StingArgsArray1.ps1 &#8220;string1&#8243;,&#8221;String2&#8221;<br>The value of arg0 string1 String2 the value of arg1 string1 String2<br>PS C:&gt; <\/font><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\">If you examine the output from the StringArgsArray1.ps1 script, you will see both elements of the <b>$args<\/b> array displayed. If you modify the StringArgsArray1.ps1 script so that you index into the array that is contained in the <b>$_<\/b> automatic variable (which represents the current item on the pipeline), you will be able to retrieve both items from the array. The revised script is called StringArgsArray2.ps1, and it is shown here: <\/p>\n<p class=\"MsoNormal\"><b>StringArgsArray2.ps1<\/p>\n<p><\/b><\/p>\n<p><span><font size=\"1\"><font><font face=\"Lucida Sans Typewriter\">$args | Foreach-Object {<br>&#8216;The value of arg0 &#8216; + $_[0] + &#8216; the value of arg1 &#8216; + $_[1]<br>} <\/font><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\">When the script is run, the correct information is displayed. This is seen here: <\/p>\n<p><span><font size=\"1\"><font><font face=\"Lucida Sans Typewriter\">PS C:&gt; StingArgsArray1.ps1 &#8220;string1&#8221;,&#8221;String2<br>The value of arg0 string1 the value of arg1 String2<br>PS C:&gt;<\/font><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><br>Now that is pretty cool huh? Well KA, we have reached the end of another exciting Hey, Scripting Guy! article. Join us tomorrow as we continue looking at handling input to a Windows PowerShell script. If you want a sneak peek of what is coming up, you can always follow us <a href=\"https:\/\/twitter.com\/scriptingguys\/\">on Twitter<\/a> or join <a href=\"http:\/\/www.new.facebook.com\/group.php?gid=5901799452\">our Facebook group<\/a>. If you get stuck while you are working on a script, don&#8217;t forget the <a href=\"http:\/\/social.technet.microsoft.com\/Forums\/en-US\/ITCG\/threads\">Official Scripting Guys Forum<\/a>, which we link to from a tab on <a title=\"our home page\" href=\"http:\/\/www.scriptingguys.com\/\">our home page<\/a>. If you are having problems finding things on the new Script Center, don&rsquo;t feel like the <a href=\"http:\/\/en.wikipedia.org\/wiki\/The_Lone_Ranger\"><font color=\"#0000ff\" face=\"Segoe\">Lone Ranger<\/font><\/a>. Keep your eyes out for Script Center 101 in which we will unravel the mysteries of the new site. <\/p>\n<p><b><span>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/span><\/b><span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p><\/span><\/h2>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! I do not think I write very complicated scripts, but quite often I find that it would be nice to be able to supply more than one value from the command line. It seems that everything I see written for Windows PowerShell uses the $args variable to get command line input, and [&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":[3,45],"class_list":["post-53063","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-scripting-guy","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! I do not think I write very complicated scripts, but quite often I find that it would be nice to be able to supply more than one value from the command line. It seems that everything I see written for Windows PowerShell uses the $args variable to get command line input, and [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/53063","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=53063"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/53063\/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=53063"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=53063"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=53063"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}