title: How do you call a function in Powershell with variable argument list
body: <p>I have a powershell function with eight parameters. Two are mandatory and two are mutually exclusive. This gives me 24 permutations of the function call.</p>
  
  <p>It seems that I should be able to craft a string based on the presence of parameter data and then execute that string to call the function, but I haven't hit upon a solution.</p>
  
  <p>This is the XML input, parameters in brackets [] are optional, | means either/or:</p>
  
  <pre><code>&lt;TextInsert TargetFile="" StartString="" [IncludeStartString="True"] [EndString="" [IncludeEndString="True"]] [SourceFile=""|InsertText=""] [IgnoreCase="True"] /&gt;
  </code></pre>
  
  <p>I had tried constructing a function call by catenating variables to the call as they were discovered, like this:</p>
  
  <pre><code>Function MakeInsertTextFunctionCallI  {
  param (
      [System.Xml.XmlElement]$Params
  )
  $IgnoreCase   = $Params.IgnoreCase
  $StartString  = $Params.StartString
  $IncludeStart = $Params.IncludeStartString
  $EndString    = $Params.EndString
  $IncludeEnd   = $Params.IncludeEndString
  $TargetFile   = $Params.TargetFile
  $InsertText   = $Params.InsertText
  $SourceFile   = $Params.SourceFile
  
  # Section A #############################################################
  $CmdStr = "InsertText -File $TargetFile -StartString $StartString"
  
  If($IncludeStart) {
      $CmdStr += " -IncludeStartString"
  }
  
  If($SourceFile) {
      $CmdStr += " -SourceFile $SourceFile"
  } else {
      $CmdStr += " -InsertText $InsertText"
  }
  
  If($EndString) {
      $CmdStr += " -EndString $EndString"
      If($IncludeEnd) {
          $CmdStr += " -IncludeEndString"
      }
  }
  
  If($IgnoreCase) {
      $CmdStr += " -IgnoreCase"
  }
  
  #    $CmdStr
  #    &amp; $CmdStr
  Invoke-Expression $CmdStr
  </code></pre>
  
  <p>But I couldn't get it work. I tried three variations of calling the function. Some of the problems involved embedded quotes in the arguments. Another issue is that I'm using this to edit markup language files so there's a lot of embedded &lt;>" and such symbols. Resulting in this error for the last attempt: Invoke-Expression : The '&lt;' operator is reserved for future use.</p>
  
  <p>The following section of code, however inelegant and unsupportable as it is, does work:</p>
  
  <pre><code># Section B ############################################################
  #Possible Parameters
  $cTargetFile =   [Convert]::ToInt32("10000000",2) #128
  $cStartString =  [Convert]::ToInt32("01000000",2) #64
  $cIncludeStart = [Convert]::ToInt32("00100000",2) #32
  $cSourceFile =   [Convert]::ToInt32("00010000",2) #16
  $cInsertText =   [Convert]::ToInt32("00001000",2) #8
  $cEndString =    [Convert]::ToInt32("00000100",2) #4
  $cIncludeEnd =   [Convert]::ToInt32("00000010",2) #2
  $cIgnoreCase =   [Convert]::ToInt32("00000001",2) #1
  
  $ParamMask = 0
  If($IgnoreCase)   { $ParamMask += $cIgnoreCase }
  If($StartString)  { $ParamMask += $cStartString }
  If($IncludeStart) { $ParamMask += $cIncludeStart }
  If($SourceFile)   { $ParamMask += $cSourceFile }
  If($InsertText)   { $ParamMask += $cInsertText }
  If($EndString)    { $ParamMask += $cEndString }
  If($IncludeEnd)   { $ParamMask += $cIncludeEnd }
  If($TargetFile)   { $ParamMask += $cTargetFile }
  
  switch($ParamMask) {
      192 { InsertText -File $TargetFile -StartString $StartString -SourceFile $SourceFile }
      193 { InsertText -File $TargetFile -StartString $StartString -SourceFile $SourceFile -IgnoreCase }
      200 { InsertText -File $TargetFile -StartString $StartString -InsertText $InsertText }
      201 { InsertText -File $TargetFile -StartString $StartString -InsertText $InsertText -IgnoreCase }
  .
  . &lt;some of the 24 permutations removed for brevity&gt;
  .
      246 { InsertText -File $TargetFile -StartString $StartString -IncludeStart -EndString $EndString -IncludeEnd -SourceFile $SourceFile }
      247 { InsertText -File $TargetFile -StartString $StartString -IncludeStart -EndString $EndString -IncludeEnd -SourceFile $SourceFile -IgnoreCase }
      238 { InsertText -File $TargetFile -StartString $StartString -IncludeStart -EndString $EndString -IncludeEnd -InsertText $InsertText }
      239 { InsertText -File $TargetFile -StartString $StartString -IncludeStart -EndString $EndString -IncludeEnd -InsertText $InsertText -IgnoreCase }
      Default { #Then log an invalid parameters error}
  }
  </code></pre>
  
  <p>I say that Section B is unsupportable because if someone wants to add another parameter to the function, calculating the bit mask and entering all the new permutation in the switch statement will be overly time consuming; as opposed to just adding one more catenation to section A.</p>
  
  <p>Does anyone have any tips for simplifying this code? Or any critique about section A that might improve it's workability?</p>