{"id":2061,"date":"2010-02-09T09:20:14","date_gmt":"2010-02-09T17:20:14","guid":{"rendered":"http:\/\/www.sapien.com\/blog\/?p=2061"},"modified":"2010-02-10T10:20:23","modified_gmt":"2010-02-10T18:20:23","slug":"primalforms-2009-the-packager-and-command-line-arguments","status":"publish","type":"post","link":"https:\/\/dev.sapien.com\/blog\/2010\/02\/09\/primalforms-2009-the-packager-and-command-line-arguments\/","title":{"rendered":"PrimalForms 2009: The Packager and Command line Arguments"},"content":{"rendered":"<p>Per forum request, this blog provides examples of how to access the packager\u2019s command line arguments as well as provide some useful functions to parse the contents. These examples apply to PrimalForms 2009\u2019s Packager and as well as PrimalScript 2009\u2019s packager.<\/p>\n<p>The package\u2019s script host provides a convenient string variable named $CommandLine. This variable contains the complete argument string that is passed to the package. To illustrate how the $CommandLine variable is used, a script package named \u201cmypackage.exe\u201d will be executed&#160; with the following arguments:<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\" width=\"450\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"450\"><font size=\"1\">             <\/p>\n<p>mypackage.exe \u2013Parameter1 Value1 \u2013Parameter2 Value2<\/p>\n<p>           <\/font><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The resulting string value of $CommandLine is as follows:<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\" width=\"450\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"450\">\n<p><font size=\"1\">$CommandLine: \u201c\u2013Parameter1\u201d \u201cValue1\u201d \u201c\u2013Parameter2\u201d \u201cValue2\u201d<\/font><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>As you can see all the parameter \/ values are in a single line and each surrounded by quotes. <\/p>\n<p><strong>Accessing the Argument Parameters<\/strong><\/p>\n<p>The simplest example of command line argument use is when a parameter is passed and there is no associated value. In order to determine if the argument is present, a simple search of the string will suffice. <\/p>\n<p>For example:<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\" width=\"450\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"450\">\n<p><font size=\"1\">mypackage.exe \/? \/a<\/font><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>In this example we only care that \u201c\/?\u201d is present; therefore, we only need to search the $CommandLine string for \u201c\/?\u201d parameter.<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\" width=\"450\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"450\">\n<p><font size=\"1\">$CommandLine: \u201c\/?\u201d \u201c\/a\u201d<\/font><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\" width=\"450\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"450\"><font size=\"1\">if($CommandLine.Contains(&quot;&quot;&quot;\/?&quot;&quot;&quot;))              <br \/>{               <br \/>&#160;&#160;&#160; Write-Host &quot;Found Parameter&quot;               <br \/>}               <br \/><\/font><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&#160;<\/p>\n<p>In other instances a value pair may be needed. The first example above illustrates the value pair.<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\" width=\"450\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"450\">\n<p><font size=\"1\">mypackage.exe \u2013Parameter1 Value1 \u2013Parameter2 Value2<\/font><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>In this case, the information will need to be parsed from the command line string which requires a more complex approach then a simple search. To help facilitate this, a function called <strong>Parse-Commandline<\/strong> was created which will parse the $CommandLine string values from the quotes and place them into a StringCollection.<\/p>\n<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\" width=\"450\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"450\">\n<p><font size=\"1\">function Parse-Commandline              <br \/>{               <br \/>&#160;&#160;&#160; Param([string]$CommandLine)               <br \/>&#160;&#160;&#160; $Arguments = New-Object System.Collections.Specialized.StringCollection               <br \/>&#160;&#160;&#160; #Find First Quote               <br \/>&#160;&#160;&#160; $index = $CommandLine.IndexOf(&#8216;&quot;&#8217;) <\/font><\/p>\n<p><font size=\"1\">&#160;&#160;&#160; while ( $index -ne -1)              <br \/>&#160;&#160;&#160; {#Continue as along as we find a quote               <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; #Find Closing Quote               <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; $closeIndex = $CommandLine.IndexOf(&#8216;&quot;&#8217;,$index + 1)               <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; if($closeIndex -eq -1)               <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; {               <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; break #Can&#8217;t find a match               <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; }               <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; $value = $CommandLine.Substring($index + 1,$closeIndex &#8211; ($index + 1))               <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; [void]$Arguments.Add($value)               <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; $index = $closeIndex <\/font><\/p>\n<p><font size=\"1\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; #Find First Quote              <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; $index = $CommandLine.IndexOf(&#8216;&quot;&#8217;,$index + 1)               <br \/>&#160;&#160;&#160; }               <br \/>&#160;&#160;&#160; return $Arguments               <br \/>}<\/font><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Using the following command line will yield these results: <\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\" width=\"450\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"450\">\n<p><font size=\"1\">$CommandLine: \u201c\u2013Parameter1\u201d \u201cValue1\u201d \u201c\u2013Parameter2\u201d \u201cValue2\u201d<\/font> <\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Results:<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\" width=\"450\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"450\">\n<p><font size=\"1\">$Parameter[0] = \u2013Parameter<\/font><\/p>\n<p><font size=\"1\">$Parameter[1] = Value1<\/font><\/p>\n<p><font size=\"1\">$Parameter[2] = \u2013Parameter2<\/font><\/p>\n<p><font size=\"1\">$Parameter[3] = Value2<\/font><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&#160;<\/p>\n<p>The parameters can be compared by simply checking each element of the collection. It can be taken even further by creating a function called <strong>Convert-ArgumentsToDictionary<\/strong> which will convert the value pairs into a Dictionary (Hashtable).&#160; <strong>Convert-ArgumentsToDictionary<\/strong> takes two parameters: The first is the parsed StringCollection and the second is a character that denotes a parameter. In the argument string above, the \u2018-\u2018 character denotes a parameter.<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\" width=\"450\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"450\">\n<p><font size=\"1\">function Convert-ArgumentsToDictionary                <br \/>{                 <br \/>&#160;&#160;&#160; Param([System.Collections.Specialized.StringCollection] $Params, [char] $ParamIndicator)                 <br \/>&#160;&#160;&#160; $Dictionary = New-Object System.Collections.Specialized.StringDictionary                 <br \/>&#160;&#160;&#160; for($index = 0; $index -lt $Params.Count; $index++)                 <br \/>&#160;&#160;&#160; {                 <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; [string]$param = $Params[$index]                 <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; #Clear the values                 <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; $key = &quot;&quot;                 <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; $value = &quot;&quot; <\/font><\/p>\n<p><font size=\"1\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; if($param.StartsWith($ParamIndicator))                <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; {                 <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; #Remove the indicator                 <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; $key = $param.Remove(0,1)                 <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if($index&#160; + 1 -lt $Params.Count)                 <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {                 <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; #Check if the next Argument is a parameter                 <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; [string]$param = $Params[$index + 1]                 <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if($param.StartsWith($ParamIndicator) -ne $true )                 <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {                 <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; #If it isn&#8217;t a parameter then set it as the value                 <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; $value = $param                 <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; $index++                 <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }                 <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }                 <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; $Dictionary[$key] = $value                 <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; }#else skip                 <br \/>&#160;&#160;&#160; }                 <br \/>&#160;&#160;&#160; return $Dictionary                 <br \/>}<\/font><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/p>\n<p>Once the parsed arguments are converted to a Dictionary, simply check for the parameter name and it will return the value. <\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\" width=\"450\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"450\">\n<p><font size=\"1\">$value = $Dictionary[\u201cParameter\u201d] <\/font><\/p>\n<p><font size=\"1\">if($value \u2013eq $null){<\/font><\/p>\n<p><font size=\"1\">Write-Host \u201cParameter = {0}\u201d \u2013 f $value<\/font><\/p>\n<p><font size=\"1\">}<\/font><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The following script utilizes the functions described above:<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\" width=\"450\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"450\"><font size=\"1\">#Verify that the $CommandLine variable exists              <br \/>if($CommandLine -ne $null -and $CommandLine -ne &quot;&quot;)               <br \/>{               <br \/>&#160;&#160;&#160; $Arguments = Parse-Commandline $CommandLine               <br \/>&#160;&#160;&#160; #Convert the Arguments. Use &#8211; as the Argument Indicator               <br \/>&#160;&#160;&#160; $Dictionary= Convert-ArgumentsToHashtable $Arguments &#8216;-&#8216;               <br \/>&#160;&#160;&#160; #Output the original command line string               <br \/>&#160;&#160;&#160; &quot;Command Line: {0}`r`n&quot; -f $CommandLine | Write-Output               <br \/>&#160;&#160;&#160; #Output the Dictionary in a formatted table               <br \/>&#160;&#160;&#160; $<font size=\"1\">Dictionary<\/font> | Format-Table @{label=&quot;Key&quot;;Expression={$_.Key}},@{label=&quot;Value&quot;;Expression={$_.Value}} | Out-String | Write-Output               <br \/>}               <br \/>else               <br \/>{               <br \/>&#160;&#160;&#160; #Not running in a packager or no command line arguments passed               <br \/>&#160;&#160;&#160; Write-Output &quot;There are no command line arguments to parse.&quot;               <br \/>}<\/font><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The script verifies the $CommandLine variable is not null because it only exists in the package\u2019s Script Host. Then the function are used to parse the $CommandLine variable and convert it to a Dictionary. Once the Dictionary is generated, the contents are formatted and displayed. <\/p>\n<p>The results are as follows:<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\" width=\"450\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"450\">\n<p><font size=\"1\">***Run Powershell***                <br \/>Command Line: &quot;-Parameter1&quot; &quot;Value1&quot; &quot;-Parameter2&quot; &quot;Value2&quot; <\/font><\/p>\n<p><font size=\"1\">Key&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Value&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br \/>&#8212;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8212;&#8211;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br \/>Parameter2&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Value2&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br \/>Parameter1&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Value1&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <\/font><\/p>\n<p><font size=\"1\">***Exiting Powershell***<\/font><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>You should now have a better understanding on how do use command line arguments with your packaged scripts. Feel free to use and customize these functions to make accessing&#160; the command line arguments quick and easy.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Per forum request, this blog provides examples of how to access the packager\u2019s command line arguments as well as provide some useful functions to parse the contents. These examples apply to PrimalForms 2009\u2019s Packager and as well as PrimalScript 2009\u2019s packager. The package\u2019s script host provides a convenient string variable named $CommandLine. This variable contains [&hellip;]<\/p>\n","protected":false},"author":10,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[283,509,410,25],"tags":[294,437,314,415],"class_list":["post-2061","post","type-post","status-publish","format-standard","hentry","category-howto","category-primalforms-software-news","category-primalscript-software-news","category-windows-powershell","tag-commandline","tag-packager","tag-primalforms","tag-primalscript-2009"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/2061","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/users\/10"}],"replies":[{"embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/comments?post=2061"}],"version-history":[{"count":11,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/2061\/revisions"}],"predecessor-version":[{"id":2073,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/2061\/revisions\/2073"}],"wp:attachment":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/media?parent=2061"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/categories?post=2061"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/tags?post=2061"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}