Comment les étendues affectent les scripts PowerShell
Dans les scripts de traitement par lots, les modifications apportées aux variables d'environnement ont un impact global sur la session en cours par défaut. Pour PowerShell, l'inverse est vrai, car les étendues permettent d'isoler les modifications d'un script. Ici, nous verrons comment les portées affectent les scripts PowerShell et comment travailler à l'intérieur 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 interpréteur de commandes fonctionne. Les étendues servent à protéger certains objets de l'environnement contre les modifications non intentionnelles effectuées par des scripts ou des fonctions. En particulier, les éléments suivants sont protégés contre les modifications par des commandes exécutées à partir d'une autre étendue, sauf spécification 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 une nouvelle instance de PowerShell. Les étendues 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 domaines qui ont une signification particulière et auxquels on peut accéder par leur nom:
- le Global scope est l'étendue créée au démarrage de PowerShell. Il inclut les variables, alias, fonctions et lecteurs PSDr intégrés à PowerShell, ainsi que ceux généré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 fait référence à la portée globale. Dans un script, il s'agit de la portée du script, etc..
- le Scénario la portée est créée lors de l'exécution d'un script. Les seules commandes qui fonctionnent dans cette étendue sont celles qui sont dans le script.
- Privé des portées peuvent être définies dans la portée actuelle pour empêcher les commandes d'autres portées de pouvoir lire ou modifier des éléments auxquels elles auraient sinon accès.
Les portées peuvent également être désignées par un numéro dans certaines commandes, la portée actuelle étant appelée zéro et ses ancêtres étant 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, à 1. Une portée qui était ensuite imbriquée dans la portée du script, telle qu'une fonction, ferait référence à la portée globale comme étant 2 Les nombres négatifs ne fonctionneront pas pour faire référence aux enfants mais la raison en sera évidente sous peu.
Comment les scopes affectent les commandes
Comme mentionné précédemment, les commandes exécutées dans une étendue n'affecteront pas celles d'une autre portée, à moins d'indication contraire. Par exemple, si $ MyVar existe dans la portée globale et si un script exécute une commande pour définir la valeur différente de $ MyVar, la version globale de $ MyVar restera inchangée tant qu'une copie de $ MyVar sera placée dans la portée de script avec la nouvelle. valeur. Si $ MyVar n'existe pas, un script le créera par défaut dans la portée du script - pas dans la portée globale. Il est important de se rappeler que vous en apprendrez plus sur la relation parent / enfant réelle entre les portées..
La relation parent / enfant des portées dans PowerShell est à sens unique. Les commandes peuvent voir, et éventuellement modifier, la portée actuelle, son parent et toutes les portées supérieures. Cependant, ils ne peuvent pas voir ou modifier les choses chez les enfants de la portée actuelle. Cela est principalement dû au fait que, une fois que vous avez migré dans une portée 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 du script, à partir de la portée globale, une fois le script terminé? Il existe de nombreux cas dans lesquels vous avez besoin que les modifications d'un script ou d'une fonction persistent après son achèvement, mais peu de cas dans lesquels vous auriez besoin d'apporter des modifications aux objets situés dans la portée du script ou de la fonction avant ou après son exécution. (Habituellement, de telles choses seront traitées dans le script ou la fonction elle-même.)
Bien sûr, quelles sont les règles sans exceptions? Les étendues privées constituent une exception à ce qui précède. 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 dotés de la propriété AllScope. Ce sont des variables spéciales et des alias pour lesquels une modification d'une portée affectera toutes les portées. Les commandes suivantes vous montreront quelles variables et quels alias ont la propriété AllScope:
Get-Variable | Où-Object $ _. Options -match 'AllScope' Get-Alias | Where-Object $ _. Options -match 'AllScope')
Scopes en action
Pour notre premier aperçu des portées en action, nous allons commencer par 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 'Modification de $ MyVar avec une fonction.' $ MyVar = 'J'ai été défini par une fonction!' "MyVar dit $ MyVar" "Vérification de la valeur actuelle de $ MyVar. ' "MyVar dit $ MyVar" "Modification de $ MyVar par script. ' $ MyVar = 'J'ai été défini par un script!' "MyVar dit $ MyVar" "FunctionScope" Vérification de la valeur finale de MyVar avant la fin du script. ' "MyVar dit $ MyVar" "
Si les scripts PowerShell fonctionnaient de la même manière que les scripts de traitement par lots, nous nous attendions à ce que la valeur de $ MyVar (ou% MyVar% dans la syntaxe de traitement par lots) passe de "Je suis une variable globale!" À "Je suis défini par un script!". et enfin à "je me suis réglé par une fonction!" où il resterait jusqu'à ce qu'il soit explicitement changé à nouveau ou que la session soit terminée. Cependant, voyez ce qui se passe réellement ici à mesure que 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 champ Script, et plus tard du champ Global,.
Comme vous pouvez le constater, la variable semblait changer au fur et à mesure de notre progression dans le script car, jusqu'à la fin de la fonction FunctionScope, nous vérifiions la variable dans la même étendue que celle modifiée précédemment. Une fois que FunctionScope a été terminé, nous sommes revenus dans la zone de script où $ MyVar n'a pas été touché par la fonction. Puis, lorsque le script a pris fin, nous sommes revenus dans la portée globale où il n'avait pas été modifié du tout..
Atteindre en dehors de la portée locale
C’est donc très bien pour vous aider à ne pas appliquer accidentellement des modifications à l’environnement au-delà de vos scripts et de vos fonctions, mais qu’en est-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 Local. Vous venez de mettre le nom de la portée au début du nom de la variable et de placer deux points entre le nom de la portée et le nom de la variable. Comme ça:
$ global: MyVar $ script: MyVar $ local: MyVar
Vous pouvez utiliser ces modificateurs lors de l'affichage et de la définition de variables. Voyons ce qui se passe avec ce script de démonstration:
Function FunctionScope "Modification de $ MyVar dans l'étendue de la fonction locale… '$ local: MyVar =" Il s'agit de MyVar dans l'étendue locale de la fonction. "' Modification de $ MyVar dans l'étendue du script… '$ script: MyVar =' MyVar était défini par un script. Maintenant défini par une fonction. "Modification de $ MyVar dans la portée globale… '$ global: MyVar =' MaVar a été définie dans la portée globale. Maintenant défini par une fonction. "Vérification de $ MyVar dans chaque étendue ... '" Local: $ local: MyVar "" Script: $ script: MyVar "" Global: $ global: MyVar "" "Obtention de la valeur actuelle de $ MyVar.' "MyVar dit $ MyVar" "Modification de $ MyVar par script. ' $ MyVar = 'J'ai été défini par un script!' "MyVar dit $ MyVar" FunctionScope 'Vérification de $ MyVar à partir de la portée du script avant de quitter.' "MyVar dit $ MyVar" "
Comme précédemment, nous allons commencer par définir la variable dans la portée globale et terminer par la vérification du résultat final de la portée globale.
Vous pouvez voir ici que FunctionScope a pu modifier la variable dans la portée du script et conserver les modifications après son achèvement. En outre, la modification de la variable dans la portée globale a persisté même après la fin du script. Cela peut être particulièrement utile si vous devez modifier de manière répétée 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 faire appel à cela chaque fois que ces changements sont nécessaires.
Comme mentionné précédemment, les numéros d'étendue peuvent également être utilisés dans certaines commandes pour modifier la variable à différents niveaux par rapport à l'étendue 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 d'étendue au lieu de référencer directement la variable avec des étendues nommées:
Function FunctionScope "Modification de $ MyVar dans l'étendue 0, par rapport à FunctionScope… 'Variable définie MyVar" Il s'agit de MyVar dans l'étendue de la fonction 0. "-Scope 0' Modification de $ MyVar dans l'étendue 1, par rapport à FunctionScope ... 'Variable définie MyVar 'MyVar a été modifié dans le scope 1, à partir d'une fonction.' -Scope 1 'Modification de $ MyVar dans le scope 2, par rapport à Functionscope…' Set-Variable MyVar 'MaVar a été modifiée dans le scope 2, à partir d'une fonction.' -Scope 2 "Vérifier $ MyVar dans chaque oscilloscope…" Scope 0: 'Get-Variable MyVar -Scope 0 -ValueOnly' Scope 1: 'Get-Variable MyVar -Scope 1 -ValueOnly' Scope 2: 'Get-Variable MyVar -Scope 2 -ValueOnly "" Obtention de la valeur actuelle de $ MyVar. ' "MyVar dit $ MyVar" "Modification de $ MyVar par script. ' $ MyVar = 'J'ai été défini par un script!' "MyVar dit $ MyVar" FunctionScope 'Vérification de $ MyVar à partir de la portée du script avant de quitter.' "MyVar dit $ MyVar" "
Semblable à avant, nous pouvons voir ici comment les commandes d'une portée peuvent modifier des objets dans sa portée parente.
Information additionnelle
Il reste encore beaucoup à faire avec les portées que cet article peut contenir. Les portées affectent plus que des variables, et il reste encore beaucoup à apprendre sur les portées privées et les variables AllScope. Pour plus d'informations utiles, vous pouvez exécuter la commande suivante à partir de PowerShell:
Obtenir de l'aide à propos_scopes
Le même fichier d’aide est également disponible sur TechNet..
Portée crédit d'image: spadassin sur openclipart