Historiquement, les utilitaires en ligne de commande dans les systèmes Unix sont mieux développés que dans Windows, mais avec l'apparition d'une nouvelle solution, la situation a changé.
Pour PowerShell, il est possible d'écrire des scripts dans un langage interprété multi-paradigme, qui contient des éléments de programmation procédurale classique, orientée objet et même fonctionnelle : instructions conditionnelles, boucles, variables, tableaux, tables de hachage, classes, gestion des erreurs, ainsi que des fonctions, des cmdlets et des pipelines. était consacré aux bases du travail dans l'environnement, et maintenant nous proposons aux lecteurs un petit guide pour les programmeurs.
Table des matières :
Le code peut être écrit dans n'importe quel éditeur de texte ou en utilisant un environnement de développement intégré — le plus simple est de prendre Windows PowerShell ISE parmi les outils fournis avec les systèmes d'exploitation serveur Microsoft. Cela est nécessaire uniquement pour des scripts suffisamment complexes : les courtes séquences de commandes sont plus facilement exécutées en mode interactif.
Commentaires
L'utilisation de commentaires est considérée comme une partie d'un bon style de programmation, tout comme des indentations et des espaces appropriés :
# Для строчных комментариев используется символ решетки — содержимое строки интерпретатор не обрабатывает.
<#
Так обозначаются начало и конец блочного комментария.
Заключенный между ними текст интерпретатор игнорирует.
#>
Variables et types
Les variables dans PowerShell sont des objets nommés. Leurs noms peuvent inclure des caractères de soulignement, ainsi que des lettres et des chiffres. Le symbole $ est toujours utilisé devant le nom, et pour déclarer une variable, il suffit d'indiquer un nom valide à l'interpréteur :

Pour initialiser une variable (lui assigner une valeur), l'opérateur d'affectation (symbole =) est utilisé :
$test = 100Une variable peut être déclarée en indiquant son type entre crochets (opérateur de conversion de type) avant le nom ou la valeur :
[int]$test = 100
$test = [int]100Il est important de comprendre que les variables dans PowerShell sont de véritables objets (classes) avec des propriétés et des méthodes, dont les types sont basés sur ceux disponibles dans .NET Core. Énumérons les principaux :
Type (classe .NET)
Description
Exemple de code
[string]
System.String
chaîne Unicode
$test = «test»
$test = ‘test’
[char]
System.Char
caractère Unicode (16 bits)
[char]$test = ‘c’
[bool]
System.Boolean
type booléen (valeur logique True ou False)
[bool]$test = $true
[int]
System.Int32
entier de trente-deux bits (32 bits)
[int]$test = 123456789
[long]
System.Int64
entier de soixante-quatre bits (64 bits)
[long]$test = 12345678910
[single]
System.Single
nombre à virgule flottante de 32 bits
[single]$test = 12345.6789
[double]
System.Double
nombre à virgule flottante de 64 bits (8 octets)
[double]$test = 123456789.101112
[decimal]
System.Decimal
nombre à virgule flottante de 128 bits (doit se terminer par d)
[decimal]$test = 12345.6789d
[DateTime]
System.DateTime
date et heure
$test = Get-Date
[array]
System.Object[]
tableau, l'indice des éléments commence à 0
$test_array = 1, 2, "test", 3, 4
[hashtable]
System.Collections.Hashtable
les tables de hachage sont des tableaux associatifs avec des clés nommées, construits selon le principe : @{clé = "valeur"}
$test_hashtable = @{one="un"; two="deux"; three="trois"}
PowerShell supporte la conversion implicite des types, de plus le type d'une variable peut changer à la volée (par exemple, à l'aide de l'opérateur d'affectation), s'il n'est pas spécifié explicitement — dans ce cas, l'interpréteur générera une erreur. On peut déterminer le type de la variable de l'exemple précédent en appelant la méthode GetType() :
$test.GetType().FullName 
Il existe un certain nombre de cmdlets pour gérer les variables. Leur liste est affichée de manière pratique à l'aide de la commande :
Get-Command -Noun Variable | ft -Property Name, Definition -AutoSize -Wrap 
Pour voir les variables déclarées et leurs valeurs, on peut utiliser le cmdlet spécial :
Get-Variable | moreCette méthode semble excessivement lourde, il est beaucoup plus pratique de travailler avec des variables via des opérateurs ou en accédant directement à leurs propriétés et méthodes. Néanmoins, les cmdlets ont leur raison d'être, car ils permettent de définir certains paramètres supplémentaires. Il est important de comprendre que les variables utilisateur sont définies uniquement dans le cadre de la session actuelle. Après la fermeture de la console ou la fin du script, elles sont supprimées.
Variables système
En plus des variables déclarées par l'utilisateur, il existe des variables intégrées (système) qui ne sont pas supprimées après la fin de la session actuelle. Elles se divisent en deux types, les données sur l'état de PowerShell étant stockées dans des variables automatiques auxquelles on ne peut pas attribuer de valeurs arbitraires. Parmi elles se trouve, par exemple, $PWD :
$PWD.Path 
Pour stocker les paramètres utilisateur, des variables de préférence sont nécessaires, dont les valeurs peuvent être modifiées. Par exemple, avec $ErrorActionPreference, on définit la réaction de l'interpréteur de commandes lorsqu'une erreur non critique se produit.
En plus des opérateurs et des cmdlets pour accéder aux variables déclarées, il existe un pseudo-dépôt Variable:. On peut y travailler de manière similaire à d'autres dépôts, les variables ressemblant alors à des objets du système de fichiers :
Get-ChildItem Variable: | moreou
ls Variable: | more 
Portées
Pour les variables dans PowerShell, il existe un concept de portée (Scope). La portée globale (Global) s'applique à toute la session en cours — elle inclut par exemple les variables système. Les variables locales (Local) ne sont accessibles que dans la portée où elles ont été définies : par exemple, à l'intérieur d'une fonction. Il existe aussi un concept de portée de script (Script), mais pour les commandes de script, elle est essentiellement locale. Par défaut, lorsque des variables sont déclarées, elles ont une portée locale, et pour changer cela, une construction spéciale est nécessaire : $Global: variable = valeur.
Par exemple, ainsi :
$Global:test = 100
Variables d'environnement
Depuis PowerShell, un autre pseudo-dépôt Env: est accessible, permettant de référencer les variables d'environnement. Lors du lancement de la console, elles sont copiées depuis le processus parent (c'est-à-dire depuis le programme ayant initié la session actuelle) et, en général, leurs valeurs initiales coïncident avec celles du panneau de configuration. Pour afficher les variables d'environnement, on utilise le cmdlet Get-ChildItem ou ses alias (pseudonymes) : ls et dir.
dir Env: 
Ces variables représentent des séquences d'octets (ou de caractères, si l'on veut), leur interprétation dépendant uniquement du programme qui les utilise. Les cmdlets *-Variable ne fonctionnent pas avec les variables d'environnement. Pour y accéder, il faudra utiliser le préfixe de disque :
$env:TEST = "Hello, World!" 
Opérateurs arithmétiques et opérateurs de comparaison
PowerShell dispose des opérateurs arithmétiques suivants : + (addition), — (soustraction), * (multiplication), / (division) et % (modulo ou reste de la division). Le résultat d'une expression arithmétique est calculé de gauche à droite selon l'ordre des opérations habituel, et des parenthèses sont utilisées pour regrouper des parties de l'expression. Les espaces entre les opérateurs sont ignorés, ils sont utilisés uniquement pour faciliter la lecture. L'opérateur + combine également des chaînes, tandis que l'opérateur * répète des chaînes. Lorsqu'on essaie d'ajouter un nombre à une chaîne, il sera converti en chaîne. De plus, PowerShell dispose de nombreux opérateurs de comparaison qui vérifient la correspondance entre deux valeurs et renvoient des booléens True ou False :
Opérateur
Description
Exemple de code
-eq
Égal / Égal à (similaire à = ou == dans d'autres langages)
$test = 100
$test -eq 123
-ne
Différent / Différent de (similaire à ou !=)
$test = 100
$test -ne 123
-gt
Plus grand que / Supérieur à (similaire à >)
$test = 100
$test -gt 123
-ge
Plus grand ou égal / Supérieur ou égal à (similaire à >=)
$test = 100
$test -ge 123
-lt
Moins que / Inférieur à (similaire à <)
$test = 100
$test -lt 123
-le
Moins ou égal / Inférieur ou égal à (similaire à <=)
$test = 100
$test -le 123
Il existe d'autres opérateurs similaires permettant par exemple de comparer des chaînes en tenant compte de caractères génériques ou d'utiliser des expressions régulières pour trouver des correspondances avec un modèle. Nous les passerons en revue en détail dans les articles suivants. Les caractères et = ne sont pas utilisés pour les comparaisons, car ils sont réservés à d'autres fins.
Opérateurs d'affectation
En plus de l'opérateur = le plus courant, il existe d'autres opérateurs d'affectation : +=, -=, *=, /= et %= qui modifient la valeur avant l'affectation. Les opérateurs unaires ++ et — se comportent de manière similaire, en augmentant ou en diminuant la valeur d'une variable - ils font également partie des opérateurs d'affectation.
Opérateurs logiques
Pour décrire des conditions complexes, il ne suffit pas de comparer. Toutes les expressions logiques peuvent être écrites à l'aide des opérateurs : -and, -or, -xor, -not et !... Ils fonctionnent comme dans d'autres langages de programmation, et il est possible d'utiliser des parenthèses pour définir l'ordre des calculs :
("Test" -eq "Test") -and (100 -eq 100)
-not (123 -gt 321)
!(123 -gt 321)
Instructions conditionnelles
Les opérateurs de branchement dans PowerShell sont standard : IF(IF…ELSE, IF…ELSEIF…ELSE) et SWITCH. Nous examinerons leur utilisation à travers des exemples :
[int]$test = 100
if ($test -eq 100) {
Write-Host "test = 100"
}
[int]$test = 50
if ($test -eq 100) {
Write-Host "test = 100"
}
else {
Write-Host "test 100"
}
[int]$test = 10
if ($test -eq 100) {
Write-Host "test = 100"
}
elseif ($test -gt 100) {
Write-Host "test > 100"
}
else {
Write-Host "test 5 ou valeur non définie"}
}
Boucles
Il existe plusieurs types de boucles dans le langage PowerShell : WHILE, DO WHILE, DO UNTIL, FOR et FOREACH.
La boucle à condition préalable fonctionne si/tant qu'elle est vraie :
[int]$test = 0
while ($test -lt 10) {
Write-Host $test
$test = $test + 1
}
Les boucles à condition postérieure s'exécutent au moins une fois, car la condition est vérifiée après l'exécution de l'itération. DO WHILE fonctionne tant que la condition est vraie, tandis que DO UNTIL fonctionne tant qu'elle est fausse :
[int]$test = 0
do {
Write-Host $test
$test = $test + 1
}
while ($test -lt 10)
[int]$test = 0
do {
Write-Host $test
$test = $test + 1
}
until ($test -gt 9)
Le nombre d'itérations de la boucle FOR est connu à l'avance :
for ([int]$test = 0; $test -lt 10; $test++) {
Write-Host $test
}
La boucle FOREACH itère sur les éléments d'un tableau ou d'une collection (tableaux associatifs) :
$test_collection = "item1", "item2", "item3"
foreach ($item in $test_collection)
{
Write-Host $item
}
Tableaux
Les variables PowerShell peuvent stocker non seulement des objets uniques (nombres, chaînes, etc.), mais aussi multiples. La forme la plus simple de ces variables est le tableau. Un tableau peut contenir plusieurs éléments, un seul élément ou être vide, c'est-à-dire ne contenir aucun élément. Pour le déclarer, on utilise l'opérateur @(), qui nous sera très utile dans l'article suivant — il est essentiel pour ajouter d'autres tableaux (créer des tableaux multidimensionnels), passer des tableaux dans des fonctions en tant qu'arguments et pour d'autres tâches de ce genre :
$test_array = @() #création d'un tableau videLors de l'initialisation d'un tableau, ses valeurs sont énumérées par des virgules (l'opérateur spécial ,) :
$test_array = @(1, 2, 3, 4) # création d'un tableau de quatre éléments Dans la plupart des cas, l'opérateur @() peut être omis :
$test_array = 1, 2, 3, 4Dans ce cas, un tableau d'un seul élément est initialisé de la manière suivante :
$test_array = , 1Pour accéder aux éléments d'un tableau, on utilise un indice entier commençant à zéro et l'opérateur d'indexation (crochets) :
$test_array[0] = 1Il est possible de spécifier plusieurs indices par virgule, y compris des indices répétitifs :
$test_array = "un", "deux", "trois", "quatre"
$test_array[0,1,2,3]
$test_array[1,1,3,3,0] 
Opérateur .. (deux points — opérateur de plage) renvoie un tableau d'entiers avec une limite supérieure et inférieure définie pour l'intervalle. Par exemple, l'expression 1..4 renvoie un tableau de quatre éléments @(1, 2, 3, 4), tandis que l'expression 8..5 renvoie un tableau @(8, 7, 6, 5).

Avec l'opérateur de plage, vous pouvez initialiser un tableau ($test_array = 1..4) ou obtenir une tranche (slice), c'est-à-dire une séquence d'éléments d'un tableau avec des indices d'un autre. Dans ce cas, un nombre négatif -1 désigne le dernier élément du tableau, -2 le pénultième, etc.
$test_array = "un", "deux", "trois", "quatre"
$test_array[0..2]
$test_array[2..0]
$test_array[-1..0]
$test_array[-2..1]Notez que les valeurs d'un tableau d'entiers peuvent être supérieures à la valeur maximale de l'indice du tableau. Dans ce cas, toutes les valeurs jusqu'à la dernière sont renvoyées :
$test_array[0..100]Si vous tentez d'accéder à un élément unique qui n'existe pas dans le tableau, la valeur $null est renvoyée.

Dans PowerShell, les tableaux peuvent contenir des éléments de types différents ou être strictement typés :
$test_array = 1, 2, "test", 3, 4
for ([int]$i = 0; $i -lt $test_array.count; $i++)
{
Write-Host $test_array[$i]
}
Où la propriété $test_array.count est le nombre d'éléments dans le tableau.
Exemple de création d'un tableau strictement typé :
[int[]]$test_array = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
Tables de hachage
Un autre type de variable de base dans PowerShell est le hachage, également appelé tableau associatif. Les hashtables sont semblables à un objet JSON et sont construits sur le principe clé-valeur. Contrairement aux tableaux ordinaires, l'accès à leurs éléments se fait par des clés nommées, qui sont des propriétés de l'objet (il est également possible d'utiliser l'opérateur d'indexation — crochets).
Une table de hachage vide est déclarée avec le symbole @ et des parenthèses :
$test_hashtable = @{}Lors de la déclaration, vous pouvez immédiatement créer des clés et leur attribuer des valeurs :
$test_hashtable = @{one="un"; two="deux"; three="trois"; "some key"="some value"}Pour ajouter un élément à la table de hachage, vous devez lui attribuer une clé qui n'existe pas encore ou utiliser la méthode Add(). Si l'attribution est faite avec une clé existante, sa valeur sera modifiée. Pour supprimer un élément de la table de hachage, vous utilisez la méthode Remove().
$test_hashtable."some key"
$test_hashtable["some key"]
$test_hashtable.Add("four", "quatre")
$test_hashtable.five = "cinq"
$test_hashtable['five'] = "remplacez la valeur"
$test_hashtable.Remove("one") 
Les variables de ce type peuvent être transmises comme arguments aux fonctions et aux cmdlets — dans l'article suivant, nous allons examiner comment cela se fait, ainsi qu'un autre type similaire : le PSCustomObject.
Fonctions
Le langage PowerShell contient tous les éléments nécessaires à la programmation procédurale, y compris les fonctions. Elles sont décrites à l'aide du mot-clé Function, suivi du nom de la fonction et du corps entre parenthèses. Si des arguments doivent être transmis à la fonction, ils peuvent être spécifiés immédiatement après le nom entre parenthèses.
function nom-de-la-fonction (argument1, ..., argumentN)
{
corps-de-la-fonction
}
Une fonction retourne toujours un résultat — il s'agit d'un tableau des résultats de toutes ses instructions, s'il y en a plusieurs. Si l'instruction est unique, une seule valeur de type correspondant est retournée. La construction return $value ajoute un élément avec la valeur $value au tableau des résultats et interrompt l'exécution de la liste d'instructions, tandis qu'une fonction vide retourne $null.
À titre d'exemple, créons une fonction qui élève un nombre au carré :
function sqr ($number)
{
return $number * $number
}
Notons que dans le corps de la fonction, toutes les variables déclarées avant son appel peuvent être utilisées, et l'appel de fonctions en PowerShell peut paraître inhabituel : les arguments (s'il y en a) ne sont pas mis entre parenthèses et sont séparés par des espaces.
sqr 2ou ainsi :
sqr -number 2En raison de la manière dont les arguments sont passés, la fonction elle-même doit parfois être mise entre parenthèses :
function test_func ($n) {}
test_func -eq $null # la fonction n'a pas été appelée
(test_func) -eq $null # le résultat de l'expression est $true 
Lors de la définition d'une fonction, des valeurs par défaut peuvent être assignées aux arguments :
function func ($arg = value) {
#corps de la fonction
}
Il existe également une autre syntaxe pour la définition des arguments d'une fonction, de plus, les paramètres peuvent être lus à partir du pipeline — tout cela sera utile dans l'article suivant, lorsque nous aborderons les modules exportés et la création de nos propres cmdlets.
Gestion des erreurs
Dans PowerShell, il existe un mécanisme Try…Catch…Finally qui permet de gérer les situations d'exception. Le code susceptible de provoquer une erreur est placé dans le bloc Try, tandis que le gestionnaire d'erreurs se trouve dans le bloc Catch. Si aucune erreur n'est survenue, le bloc Catch n'est pas exécuté. Le bloc Finally s'exécute après le bloc Try indépendamment de l'occurrence d'une erreur, et il peut y avoir plusieurs blocs Catch pour des exceptions de types différents. L'exception elle-même est enregistrée dans une variable par défaut qui ne nécessite pas de déclaration ($_) et peut être facilement extraite. Dans l'exemple ci-dessous, nous mettons en œuvre une protection contre l'entrée d'une valeur incorrecte :
try {
[int]$test = Read-Host "Entrez un nombre"
100 / $test
} catch {
Write-Warning "Nombre incorrect"
Write-Host $_
}

Ainsi, nous pouvons conclure notre discussion sur les bases de la programmation en PowerShell. Dans les prochains articles, nous examinerons plus en détail le travail avec des variables de différents types, des collections, des expressions régulières, la création de fonctions, de modules et de cmdlets personnalisés, ainsi que la programmation orientée objet.
Source : habr.com
