Passer une variable par référence en PowerShell

Comment passer une variable par référence en PowerShell ? Telle est la question qui m’a assailli alors que je venais de finir la réécrire une application C++ en PowerShell. Pour schématiser, le script contient des fonctions qui traitent des données issu d’un pipe, et un compteur s’incrémente dans le niveau le plus bas.

Function f{
   param([parameter(ValueFromPipeline=$True)] $objects)
   Process {
      Foreach($object in $objects){
         #conditions
         manyRes $objet | f2
         #utiliser compteur
      }
   }
}

Function f2{
   param([parameter(ValueFromPipeline=$True)] $objects)
   Process {
      Foreach($object in $objects){
         #conditions et compteur
      }
   }
}

AlotOfRes | f
</pre>

## Deux possibilités pour passer des variables par référence {#deux-possibilités-pour-passer-des-variables-par-référence}

  * La référence classique avec **[ref]** qui fonctionne comme le **out** en C#.
  * Utiliser les scopes de variable avec les commandlets ***-Variable**

Lexemple suivant illustre les 2 mécanismes.

<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-powershell" data-lang="powershell">New-Variable -Name <span style="color:#e6db74">&#39;varValueType&#39;</span> -Scope <span style="color:#e6db74">&#39;Script&#39;</span> -Value <span style="color:#e6db74">&#39;newValue&#39;</span>

<span style="color:#75715e"># not working</span>
<span style="color:#66d9ef">function</span> ChangeFail(){
   <span style="color:#e6db74">&#34;MaFonction avant : $varValueType&#34;</span>
   $varValueType = <span style="color:#e6db74">&#39;ChangeFail&#39;</span>
   <span style="color:#e6db74">&#34;MaFonction apres : $varValueType&#34;</span>
}

<span style="color:#75715e"># working by reference</span>
<span style="color:#75715e"># note : Reference Type do not need [ref]</span>
<span style="color:#66d9ef">function</span> ChangeRef{
   <span style="color:#66d9ef">param</span>(
      <span style="color:#66d9ef">[ref]</span>$varRef
   )
   <span style="color:#e6db74">&#34;ChangeRef avant : </span>$($varRef.Value)<span style="color:#e6db74">&#34;</span>
   $varRef.Value= <span style="color:#e6db74">&#39;ChangeRef&#39;</span>
   <span style="color:#e6db74">&#34;ChangeRef apres : </span>$($varRef.Value)<span style="color:#e6db74">&#34;</span>
}

<span style="color:#75715e">#working by Set-Variable</span>
<span style="color:#66d9ef">function</span> ChangeSetVariable(){
   <span style="color:#e6db74">&#34;ChangeSetVariable avant : $varValueType&#34;</span>
   Set-Variable -Name <span style="color:#e6db74">&#39;varValueType&#39;</span> -Value <span style="color:#e6db74">&#39;ChangeSetVariable&#39;</span> -Scope <span style="color:#e6db74">&#39;Script&#39;</span>
   <span style="color:#e6db74">&#34;ChangeSetVariable apres : $varValueType&#34;</span>
}

<span style="color:#66d9ef">function</span> main(){
   <span style="color:#e6db74">&#34;Main: $varValueType&#34;</span>
   ChangeFail
   <span style="color:#e6db74">&#34;Main: $varValueType&#34;</span>
   ChangeRef -varRef (<span style="color:#66d9ef">[ref]</span>$varValueType)
   <span style="color:#e6db74">&#34;Main: $varValueType&#34;</span>
   <span style="color:#75715e">#$varValueType2.key</span>
   ChangeSetVariable
   <span style="color:#e6db74">&#34;Main: $varValueType&#34;</span>
}

main&lt;/pre&gt;

&lt;div class=<span style="color:#e6db74">&#34;highlight&#34;</span>&gt;&lt;pre style=<span style="color:#e6db74">&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;</span>&gt;&lt;code class=<span style="color:#e6db74">&#34;language-bash&#34;</span> data-lang=<span style="color:#e6db74">&#34;bash&#34;</span>&gt;Main<span style="color:#960050;background-color:#1e0010">:</span> ChangeSetVariable
MaFonction avant <span style="color:#960050;background-color:#1e0010">:</span> ChangeSetVariable
MaFonction apres <span style="color:#960050;background-color:#1e0010">:</span> ChangeFail
Main<span style="color:#960050;background-color:#1e0010">:</span> ChangeSetVariable
ChangeRef avant <span style="color:#960050;background-color:#1e0010">:</span> ChangeSetVariable
ChangeRef apres <span style="color:#960050;background-color:#1e0010">:</span> ChangeRef
Main<span style="color:#960050;background-color:#1e0010">:</span> ChangeRef
ChangeSetVariable avant <span style="color:#960050;background-color:#1e0010">:</span> ChangeRef
ChangeSetVariable apres <span style="color:#960050;background-color:#1e0010">:</span> ChangeSetVariable
Main<span style="color:#960050;background-color:#1e0010">:</span> ChangeSetVariable&amp;lt;/pre&amp;gt;

&lt;span style=<span style="color:#e6db74">&#34;color:#75715e&#34;</span>&gt;<span style="color:#75715e">## Les cmdlets associées aux variables et les scopes {#les-cmdlets-associées-aux-variables-et-les-scopes}&lt;/span&gt;</span>

Pour manipuler les variables, les commandlets ***-Variable** sont intuitives<span style="color:#960050;background-color:#1e0010">:</span>

  * Clear-Variable <span style="color:#960050;background-color:#1e0010">:</span> supprimer la valeur d<span style="color:#960050;background-color:#1e0010"></span>une variable
  * Get-Variable <span style="color:#960050;background-color:#1e0010">:</span> obtenir une variable
  * New-Variable <span style="color:#960050;background-color:#1e0010">:</span> créer une nouvelle variable
  * Remove-Variable <span style="color:#960050;background-color:#1e0010">:</span> supprimer une variable et sa valeur
  * Set-Variable<span style="color:#960050;background-color:#1e0010">:</span> définir une variable

Par contre, tester l<span style="color:#960050;background-color:#1e0010"></span>existence d<span style="color:#960050;background-color:#1e0010"></span>une variable est moins trivial. &lt;span style=<span style="color:#e6db74">&#34;color:#ae81ff&#34;</span>&gt;2&lt;/span&gt; possibilités s<span style="color:#960050;background-color:#1e0010">’</span>offrent à vous <span style="color:#960050;background-color:#1e0010">:</span>

  * Test-Path Variable<span style="color:#960050;background-color:#1e0010">:</span>&amp;lt;scope&amp;gt;<span style="color:#960050;background-color:#1e0010">:</span>&amp;lt;variableName&amp;gt;&amp;lt;/variableName&amp;gt;&amp;lt;/scope&amp;gt;
  * Get-Variable en cachant les erreurs et vérifier le code de retour $?

&amp;lt;div class&lt;span style=<span style="color:#e6db74">&#34;color:#f92672&#34;</span>&gt;=&lt;/span&gt;&lt;span style=<span style="color:#e6db74">&#34;color:#e6db74&#34;</span>&gt;&amp;<span style="color:#75715e">#34;highlight&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;pre style&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;code class&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;language-powershell&amp;#34;&lt;/span&gt; data-lang&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;powershell&amp;#34;&lt;/span&gt;&amp;gt;Test-Path Variable&amp;lt;span style&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;color:#960050;background-color:#1e0010&amp;#34;&lt;/span&gt;&amp;gt;:&amp;lt;/span&amp;gt;script&amp;lt;span style&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;color:#960050;background-color:#1e0010&amp;#34;&lt;/span&gt;&amp;gt;:&amp;lt;/span&amp;gt;VarExist</span>
&amp;amp;amp;gt; True
Get-Variable -Name VarExist -Scope &amp;lt;span style&lt;span style=<span style="color:#e6db74">&#34;color:#f92672&#34;</span>&gt;=&lt;/span&gt;&lt;span style=<span style="color:#e6db74">&#34;color:#e6db74&#34;</span>&gt;&amp;<span style="color:#75715e">#34;color:#e6db74&amp;#34;&lt;/span&gt;&amp;gt;&amp;amp;&lt;span style=&#34;color:#75715e&#34;&gt;#39;Script&amp;amp;#39;&amp;lt;/span&amp;gt; -ErrorAction SilentlyContinue&lt;/span&gt;</span>
$?
&amp;amp;amp;gt; True

Test-Path Variable&amp;lt;span style&lt;span style=<span style="color:#e6db74">&#34;color:#f92672&#34;</span>&gt;=&lt;/span&gt;&lt;span style=<span style="color:#e6db74">&#34;color:#e6db74&#34;</span>&gt;&amp;<span style="color:#75715e">#34;color:#960050;background-color:#1e0010&amp;#34;&lt;/span&gt;&amp;gt;:&amp;lt;/span&amp;gt;script&amp;lt;span style&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;color:#960050;background-color:#1e0010&amp;#34;&lt;/span&gt;&amp;gt;:&amp;lt;/span&amp;gt;VarNotExist</span>
&amp;amp;amp;gt; False
Get-Variable -Name VarNotExist -Scope &amp;lt;span style&lt;span style=<span style="color:#e6db74">&#34;color:#f92672&#34;</span>&gt;=&lt;/span&gt;&lt;span style=<span style="color:#e6db74">&#34;color:#e6db74&#34;</span>&gt;&amp;<span style="color:#75715e">#34;color:#e6db74&amp;#34;&lt;/span&gt;&amp;gt;&amp;amp;&lt;span style=&#34;color:#75715e&#34;&gt;#39;Script&amp;amp;#39;&amp;lt;/span&amp;gt; -ErrorAction SilentlyContinue&lt;/span&gt;</span>
$?
&amp;amp;amp;gt; False
&amp;amp;lt;/pre&amp;amp;gt;

J&amp;lt;span style&lt;span style=<span style="color:#e6db74">&#34;color:#f92672&#34;</span>&gt;=&lt;/span&gt;&lt;span style=<span style="color:#e6db74">&#34;color:#e6db74&#34;</span>&gt;&amp;<span style="color:#75715e">#34;color:#960050;background-color:#1e0010&amp;#34;&lt;/span&gt;&amp;gt;’&amp;lt;/span&amp;gt;ai apprécié &amp;lt;span style&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;color:#66d9ef&amp;#34;&lt;/span&gt;&amp;gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;ref&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;&amp;lt;/span&amp;gt; pour son côté rassurant en tant que développeur. Pourtant j&amp;lt;span style&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;color:#960050;background-color:#1e0010&amp;#34;&lt;/span&gt;&amp;gt;’&amp;lt;/span&amp;gt;ai choisi Set-Variable pour la propreté du code.</span>

Qu&amp;lt;span style&lt;span style=<span style="color:#e6db74">&#34;color:#f92672&#34;</span>&gt;=&lt;/span&gt;&lt;span style=<span style="color:#e6db74">&#34;color:#e6db74&#34;</span>&gt;&amp;<span style="color:#75715e">#34;color:#960050;background-color:#1e0010&amp;#34;&lt;/span&gt;&amp;gt;’&amp;lt;/span&amp;gt;aurez vous choisi dans cette situation?</span>

**Références &amp;lt;span style&lt;span style=<span style="color:#e6db74">&#34;color:#f92672&#34;</span>&gt;=&lt;/span&gt;&lt;span style=<span style="color:#e6db74">&#34;color:#e6db74&#34;</span>&gt;&amp;<span style="color:#75715e">#34;color:#960050;background-color:#1e0010&amp;#34;&lt;/span&gt;&amp;gt;:&amp;lt;/span&amp;gt;**</span>

&amp;lt;span style&lt;span style=<span style="color:#e6db74">&#34;color:#f92672&#34;</span>&gt;=&lt;/span&gt;&lt;span style=<span style="color:#e6db74">&#34;color:#e6db74&#34;</span>&gt;&amp;<span style="color:#75715e">#34;color:#66d9ef&amp;#34;&lt;/span&gt;&amp;gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;About_Scopes sur la technet&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;1&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;&amp;lt;/span&amp;gt;</span>

 &lt;span style=<span style="color:#e6db74">&#34;color:#f92672&#34;</span>&gt;[&lt;/span&gt;1&lt;span style=<span style="color:#e6db74">&#34;color:#f92672&#34;</span>&gt;]&lt;/span&gt;&amp;lt;span style&lt;span style=<span style="color:#e6db74">&#34;color:#f92672&#34;</span>&gt;=&lt;/span&gt;&lt;span style=<span style="color:#e6db74">&#34;color:#e6db74&#34;</span>&gt;&amp;<span style="color:#75715e">#34;color:#960050;background-color:#1e0010&amp;#34;&lt;/span&gt;&amp;gt;:&amp;lt;/span&amp;gt; https&amp;lt;span style&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;color:#960050;background-color:#1e0010&amp;#34;&lt;/span&gt;&amp;gt;:&amp;lt;/span&amp;gt;//technet.microsoft.com/en-us/library/hh847849.aspx&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</span></code></pre></div>