in

Comment les étendues affectent les scripts PowerShell

Dans les scripts batch, les modifications apportées aux variables d’environnement ont un impact global sur la session en cours par défaut. Pour PowerShell, exactement le contraire est vrai car les étendues sont utilisées pour isoler les modifications d’un script. Ici, nous allons explorer comment les étendues affectent les scripts PowerShell et comment travailler dans et autour d’eux.

Qu’est-ce qu’une portée?

Dans PowerShell, une «étendue» fait référence à l’environnement actuel dans lequel un script ou un shell de commande fonctionne. Les étendues sont utilisées pour protéger certains objets de l’environnement contre toute modification involontaire par des scripts ou des fonctions. En particulier, les éléments suivants sont protégés contre la modification par des commandes exécutées à partir d’une autre portée, sauf indication contraire par les paramètres de ces commandes:

  • Variables
  • Alias
  • Les fonctions
  • Disques PowerShell (PSDrives)

De nouvelles étendues sont créées chaque fois que vous exécutez un script ou une fonction, ou lorsque vous créez une nouvelle session ou instance de PowerShell. Les portées créées en exécutant des scripts et des fonctions ont une relation «parent / enfant» avec la portée à partir de laquelle elles ont été créées. Il existe quelques portées qui ont des significations particulièrement spéciales et sont accessibles par leur nom:

  • le Global scope est l’étendue créée au démarrage de PowerShell. Il comprend les variables, alias, fonctions et PSDrives intégrés à PowerShell, ainsi que ceux créés par votre profil PowerShell.
  • le Local La portée fait référence à quelle que soit la portée actuelle. Lorsque vous démarrez PowerShell, il fera référence à la portée globale, dans un script, ce sera la portée de script, etc.
  • le Scénario l’étendue est créée lors de l’exécution d’un script. Les seules commandes qui fonctionnent dans cette portée sont celles qui se trouvent dans le script.
  • Privé les étendues peuvent être définies dans l’étendue actuelle, pour empêcher les commandes d’autres étendues de pouvoir lire ou modifier les éléments auxquels elles pourraient autrement avoir accès.

Les étendues peuvent également être désignées par un nombre dans certaines commandes, où l’étendue actuelle est appelée zéro et ses ancêtres sont référencés par des entiers croissants. Par exemple, dans un script exécuté à partir de la portée globale, la portée du script serait 0 et la portée globale serait 1. Une portée qui était davantage imbriquée dans la portée du script, telle qu’une fonction, ferait référence à la portée globale comme 2 Cependant, les nombres négatifs ne fonctionneront pas pour référencer les portées enfants – la raison en sera bientôt évidente.

Comment les étendues affectent les commandes

Comme mentionné précédemment, les commandes exécutées dans une portée n’affecteront pas les choses dans une autre portée, sauf indication contraire. Par exemple, si $ MyVar existe dans la portée Global et qu’un script exécute une commande pour définir $ MyVar sur une valeur différente, la version globale de $ MyVar restera inchangée tandis qu’une copie de $ MyVar est placée dans la portée Script avec le nouveau valeur. Si $ MyVar n’existe pas, un script le créera dans la portée Script par défaut – pas dans la portée Global. Il est important de s’en souvenir lorsque vous en apprenez davantage sur la relation parent / enfant réelle entre les portées.

La relation parent / enfant des étendues dans PowerShell est à sens unique. Les commandes peuvent voir dans, et éventuellement modifier, la portée actuelle, son parent et toutes les étendues au-dessus. Cependant, ils ne peuvent ni voir ni modifier les éléments des enfants de la portée actuelle. Ceci est principalement dû au fait que, une fois que vous êtes passé dans une étendue parent, la portée enfant a déjà été détruite car elle a rempli son objectif. Par exemple, pourquoi devriez-vous voir ou modifier une variable dans la portée Script, à partir de la portée Global, une fois le script terminé? Il existe de nombreux cas où vous avez besoin que les modifications d’un script ou d’une fonction persistent au-delà de son achèvement, mais pas tellement où vous devez apporter des modifications aux objets dans la portée du script ou de la fonction avant ou après son exécution. (Habituellement, de telles choses seront gérées dans le cadre du script ou de la fonction elle-même de toute façon.)

Bien sûr, que sont les règles sans exceptions? Une exception à ce qui précède concerne les étendues privées. Les objets des étendues privées ne sont accessibles qu’aux commandes exécutées dans l’étendue à partir de laquelle ils ont été créés. Une autre exception importante concerne les éléments qui ont la propriété AllScope. Ce sont des variables spéciales et des alias pour lesquels une modification de n’importe quelle étendue affectera toutes les étendues. Les commandes suivantes vous montreront quelles variables et quels alias ont la propriété AllScope:

Get-Variable | Where-Object {$_.Options -match 'AllScope'}
Get-Alias | Where-Object {$_.Options -match 'AllScope')

Scopes en action

Pour notre premier aperçu des étendues en action, nous allons commencer dans une session PowerShell où la variable $ MyVar a été définie sur une chaîne, «  Je suis une variable globale!  », À partir de la ligne de commande. Ensuite, le script suivant sera exécuté à partir d’un fichier appelé Scope-Demo.ps1:

Function FunctionScope
{
    'Changing $MyVar with a function.'
    $MyVar="I got set by a function!"
    "MyVar says $MyVar"
}
''
'Checking current value of $MyVar.'
"MyVar says $MyVar"
''
'Changing $MyVar by script.'
$MyVar="I got set by a script!"
"MyVar says $MyVar"
''
FunctionScope
''
'Checking final value of MyVar before script exit.'
"MyVar says $MyVar"
''

Si les scripts PowerShell fonctionnaient de la même manière que les scripts batch, nous nous attendrions à ce que la valeur de $ MyVar (ou% MyVar% dans la syntaxe batch) passe de «Je suis une variable globale!» À «J’ai été défini par un script! , et enfin à « Je me suis fait régler par une fonction! » où il resterait jusqu’à ce qu’il soit explicitement modifié à nouveau ou que la session soit terminée. Cependant, voyez ce qui se passe réellement ici lorsque nous parcourons chacune des portées – en particulier, une fois que la fonction FunctionScope a terminé son travail et que nous vérifions à nouveau la variable à partir du script, et plus tard de la portée globale.

image

Comme vous pouvez le voir, la variable a semblé changer au fur et à mesure que nous nous déplaçions dans le script car, jusqu’à ce que la fonction FunctionScope soit terminée, nous vérifiions la variable à partir de la même portée qu’elle avait été modifiée pour la dernière fois. Une fois FunctionScope terminé, nous sommes retournés dans la portée Script où $ MyVar n’a pas été touché par la fonction. Ensuite, lorsque le script s’est terminé, nous sommes revenus dans la portée globale où il n’avait pas été modifié du tout.

Sortir du cadre local

Donc, tout cela est bien beau pour vous aider à éviter d’appliquer accidentellement des modifications à l’environnement au-delà de vos scripts et fonctions, mais que se passe-t-il si vous voulez réellement apporter de telles modifications? Il existe une syntaxe spéciale et assez simple pour créer et modifier des objets au-delà de la portée locale. Vous mettez simplement le nom de la portée au début du nom de la variable, et mettez un deux-points entre la portée et les noms de variable. Comme ça:

$global:MyVar
$script:MyVar
$local:MyVar

Vous pouvez utiliser ces modificateurs à la fois lors de l’affichage et de la définition des variables. Voyons ce qui se passe avec ce script de démonstration:

Function FunctionScope
{
    ''
    'Changing $MyVar in the local function scope...'
    $local:MyVar = "This is MyVar in the function's local scope."
    'Changing $MyVar in the script scope...'
    $script:MyVar="MyVar used to be set by a script. Now set by a function."
    'Changing $MyVar in the global scope...'
    $global:MyVar="MyVar was set in the global scope. Now set by a function."
    ''
    'Checking $MyVar in each scope...'
    "Local: $local:MyVar"
    "Script: $script:MyVar"
    "Global: $global:MyVar"
    ''
}
''
'Getting current value of $MyVar.'
"MyVar says $MyVar"
''
'Changing $MyVar by script.'
$MyVar="I got set by a script!"
"MyVar says $MyVar"

FunctionScope

'Checking $MyVar from script scope before exit.'
"MyVar says $MyVar"
''

Comme précédemment, nous allons commencer par définir la variable dans la portée globale et terminer par vérifier le résultat final de la portée globale.

image

Ici, vous pouvez voir que FunctionScope a pu modifier la variable dans la portée du script et que les modifications sont conservées après son exécution. En outre, la modification de la variable dans la portée globale a persisté même après la fermeture du script. Cela peut être particulièrement utile si vous devez modifier à plusieurs reprises des variables dans un script, ou dans la portée globale, en utilisant le même code – vous définissez simplement une fonction ou un script écrit pour modifier la variable où et comment vous en avez besoin, et faites appel à cela chaque fois que ces changements sont nécessaires.

Comme mentionné précédemment, les numéros de portée peuvent également être utilisés dans certaines commandes pour modifier la variable à différents niveaux par rapport à la portée locale. Voici le même script utilisé dans le deuxième exemple ci-dessus, mais avec la fonction modifiée pour utiliser les commandes Get-Variable et Set-Variable avec des numéros de portée au lieu de référencer directement la variable avec des portées nommées:

Function FunctionScope
{
    ''
    'Changing $MyVar in scope 0, relative to FunctionScope...'
    Set-Variable MyVar "This is MyVar in the function's scope 0." –Scope 0
    'Changing $MyVar in scope 1, relative to FunctionScope...'
    Set-Variable MyVar 'MyVar was changed in scope 1, from a function.' –Scope 1
    'Changing $MyVar in scope 2, relative to Functionscope...'
    Set-Variable MyVar 'MyVar was changed in scope 2, from a function.' –Scope 2
    ''
    'Checking $MyVar in each scope...'
    ‘Scope 0:’
    Get-Variable MyVar –Scope 0 –ValueOnly
    ‘Scope 1:’
    Get-Variable MyVar –Scope 1 –ValueOnly
    ‘Scope 2:’
    Get-Variable MyVar –Scope 2 –ValueOnly
    ''
}
''
'Getting current value of $MyVar.'
"MyVar says $MyVar"
''
'Changing $MyVar by script.'
$MyVar="I got set by a script!"
"MyVar says $MyVar"

FunctionScope

'Checking $MyVar from script scope before exit.'
"MyVar says $MyVar"
''
image

Comme précédemment, nous pouvons voir ici comment les commandes d’une portée peuvent modifier les objets de sa portée parent.

Information additionnelle

Il y a encore beaucoup plus à faire avec les étendues que ce que peut contenir cet article. Les étendues affectent plus que de simples variables, et il y a encore plus à apprendre sur les étendues privées et les variables AllScope. Pour plus d’informations utiles, vous pouvez exécuter la commande suivante à partir de PowerShell:

Get-Help about_scopes

Le même fichier d’aide est également disponible sur TechNet.

Crédit d’image de la portée: spadassin sur openclipart

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Comment ajuster votre SSD dans Ubuntu pour de meilleures performances

Comment ajuster votre SSD dans Ubuntu pour de meilleures performances

Comment utiliser votre Amazon Echo comme interphone avec Drop In

Comment utiliser votre Amazon Echo comme interphone avec Drop In