title: PowerShell "break" keeps changing the rules
body: <p>This line of code has - without editing it - changed it's behavior over the last several days - several times:</p>
  
  <pre><code>try {
      $testfile = "c:\users\***RedactedForSecurity***\desktop\psfcatalog\copy_conversions_weekly_report.csv"
      write-log((Get-Date -Format o) + "     get-sqlhelper")
      $sqlhelper = get-sqlhelper -serverinstance '***RedactedForSecurity***' -database '***RedactedForSecurity***' -username '***RedactedForSecurity***' -password '***RedactedForSecurity***'
  
      Function Create-TableString{ 
          Param(
              [Parameter(Mandatory=$true)]
              [string]$tableName,
              [Parameter(Mandatory=$true)]
              [string]$Fields
          )
          [string]$SQL = "CREATE TABLE " + $tableName + '(' + $Fields + ')'
          Write-Host $SQL
          return $SQL
      }
  
      write-log((Get-Date -Format o) + "     finding first line of CSV data in file")
      gc $testfile | % {
          if ($_ -match "report fields") {
              $line = $_.ReadCount
              break
          }
      }
  
      [string]$fieldNamesSQL = gc $testfile |
          select -Skip $line -First 10 |
          ConvertFrom-Csv |
          Out-DataTable |
          % {$fieldNamesSQL += $Col.ColumnName + " VARCAR(255)  NULL, "} -End {$fieldNamesSQL.TrimEnd(',', ' ')}
  
      Write-Host $fieldNamesSQL
      Write-Host $csvHeaders
  } catch {
      $msg = command 2&gt;&amp;1
      Write-Host $_.exception.message
      Write-Host $_.exception.itemname
      Write-Host $_.exception.message
      Write-Host $msg
  }
  </code></pre>
  
  <p>Alright here's the thing - notice the portion of the script:</p>
  
  <pre><code>gc $testfile | % {
      if ($_ -match "report fields") {
          $line = $_.ReadCount
          break
      }
  }
  </code></pre>
  
  <p>That portion worked fine for about a day and then <code>break</code> started to stop execution of the entire script instead of just beak the loop.  How can it work for a day and then change?  Anyway, I came up with a solution where I would wrap the whole piece with <code>{}</code> and then recursivly execute it in my next call:</p>
  
  <pre><code>{gc $testfile | % {
      if ($_ -match "report fields") {
          $line = $_.ReadCount
          break
      }
  }}
  
  [string]$fieldNamesSQL = gc $testfile |
      select -Skip $line -First 10 |
      ConvertFrom-Csv |
      Out-DataTable |
      % {$fieldNamesSQL += $Col.ColumnName + " VARCAR(255)  NULL, "} -End {$fieldNamesSQL.TrimEnd(',', ' ')}
  </code></pre>
  
  <p>With this setup when <code>$line</code> is called, it evaluates the previous line and script execution continues seamlessly.</p>
  
  <p>A day later...</p>
  
  <p>Now the same script is throwing an error:</p>
  
  <blockquote>
    <p>Cannot validate argument on parameter 'Skip'. The argument is null, empty, or an element of the argument collection contains a null value. Supply a collection that does not contain any null values and then try the command again.</p>
  </blockquote>
  
  <p>What is happening?</p>
  
  <p><strong>Edit</strong></p>
  
  <p>This is not a duplicate.  I'm aware of the <code>foreach</code> alias problem.  The question is why the PowerShell runtime changes its evaluation between executions.  Ie:  I didn't change the script but the execution changed.  Why would PowerShell evaluate <code>foreach</code> to an operator on one day and evaluate it to <code>ForEach-Object</code> on another day?</p>
  
  <p>Things I've found:</p>
  
  <p>It seems that PowerShell persists certain values between executions.  For instance if I set a string to value1 and run the script.  Then I set it to another value2 and run the script, but the value remains value1 when I <code>Write-Host</code>.  I have to restart the shell and sometimes the machine to get it to evaluate correctly.  It seems random so far as to when this happens - which probably just means I don't understand it.</p>
  
  <p>My best guess so far is that when PowerShell interprets foreach it does so recursively so a function further down the script could cause it to evaluate differently from call to call.</p>