Comment créer son premier script
PowerShell ?
21/11/2017 Florian Burnel 5 Commentaires Powershell, Scripting
Sommaire [-]
I. Présentation
II. Quel éditeur utiliser pour un script PowerShell ?
III. Quelques bases
o A. Le nom des commandes / cmdlets
o B. Obtenir de l'aide
o C. Les alias
o D. L'exécution des scripts
o E. Une panoplie de modules
o F. Jouer avec les variables
o G. Le pipeline
IV. A la conquête de notre premier script
V. Interroger l'annuaire Active Directory en PowerShell
VI. Et ensuite ?
I. Présentation
Le langage PowerShell est désormais incontournable pour l'administration des
systèmes d'exploitation Windows, ainsi que pour l'automatisation de certaines
tâches. Dans le même temps, Microsoft développe une version compatible Linux,
ce côté multi-plateformes le rend, à mon sens, encore plus attractif et son
apprentissage pertinent.
Au-delà du scripting, PowerShell est un véritable outil d'administration
et d'automatisation.
Pour votre premier script PowerShell, difficile de deviner quel sujet il traitera, les
options sont nombreuses... Mais il y a fort à parier que vous allez requêter
l'annuaire Active Directory de votre entreprise assez rapidement. En tout cas,
l'objectif principal de cet article est de vous donner les bases pour avoir une
bonne approche dans la rédaction de votre premier script PowerShell.
II. Quel éditeur utiliser pour un script
PowerShell ?
La première question qui va se poser, c'est de savoir quel éditeur vous allez
utiliser pour rédiger votre script. Oubliez le Bloc-note, Notepad++ ou la console
PowerShell directement. Ce n'est pas adapté.
Je vous recommande deux outils : PowerShell ISE, qui est l'éditeur intégré à
Windows et qui est adapté au scripting PowerShell, il contient notamment l'aide
intégré, l'auto-complétion ainsi qu'une console PowerShell. De base et sans
configuration particulière, il vous permettra de bénéficier d'un environnement
simple et préconfiguré pour débuter avec PowerShell.
Le second outil n'est autre que Visual Studio Code, VSCode pour les intimes, qui
ne se limite pas qu'à PowerShell contrairement à l'ISE puisque l'on pourra installer
différentes extensions, dont PowerShell. On pourra ensuite le configurer à souhait
avec les nombreux paramètres disponibles, mais aussi l'interconnecter avec
d'autres services comme GitHub et intégrer d'autres langages.
Remarque : Au même titre que PowerShell ISE, l'outil VSCode est disponible en
version 32 bits et 64 bits.
En fait, et ça reste mon avis, je pense qu'il vaut mieux commencer avec
PowerShell ISE, car il est super simple d'utilisation et il s'agit de l'outil natif. Puis,
par la suite, lorsque l'on souhaite personnaliser de manière plus avancée son
éditeur PowerShell, il faudra basculer vers VSCode.
A
perçu de l'interface PowerShell ISE
Pour commencer, ces trois boutons classiques sont à connaître, car ils sont bien
pratiques :
Je vous propose de consulter cet article qui détaille notamment les nouveautés de
PowerShell ISE 5.0 par rapport aux versions précédentes : PowerShell ISE 5.0, les
nouveautés - notamment l'excellente fonctionnalité IntelliSense disponible depuis
la version 3.0 et qui permet l'auto-complétion des commandes et de vous aider
dans la syntaxe de manière efficace.
Maintenant que l'on a identifié un éditeur de code, passons à quelques bases
théoriques sur PowerShell.
III. Quelques bases
Afin de vous aiguiller dans la rédaction de vos premières lignes de code
PowerShell et pour vous donner quelques bases bien utiles, voici ci-dessous
quelques notions abordées, volontairement sans trop de détails pour une
première approche.
A. Le nom des commandes / cmdlets
Vous verrez au fil du temps que vous pouvez deviner le nom d'une commande
PowerShell, même si vous ne la connaissez pas, simplement parce qu'il y a une
convention de nommage stricte pour le nom des cmdlets.
En fait, Microsoft fournit une liste de verbes approuvés et qui peuvent
être utilisés pour le nom des commandes, que ce soit pour les commandes
officielles ou celles des modules communautaires. Une commande PowerShell suit
la convention de nommage suivante : Verbe-Nom.
Par exemple, le verbe "Get" ciblera les commandes qui permettent d'obtenir des
informations. Pour obtenir la liste des services, ce sera "Get-Service". Pour arrêter
un service, on utilisera le verbe "Stop" ce qui donnera "Stop-Service" et pour le
démarrer "Start-Service". Simple, non ?
Plus d'informations sur les verbes approuvés : Approved Verbs for Windows
PowerShell Commands
Astuce : le cmdlet "Get-Command" permet de lister les commandes disponibles
sur votre machine, ce qui peut varier selon votre version de PowerShell et les
modules disponibles sur l'hôte local. Ainsi, on peut rechercher facilement une
commande en s'appuyant sur un mot clé.
Reprenons le terme "Service" et recherchons toutes les commandes qui
contiennent ce terme :
Get-Command *Service
Ce qui nous permet d'obtenir la liste des commandes :
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet Get-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet New-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Restart-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Resume-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Set-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Start-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Stop-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Suspend-Service 3.1.0.0 Microsoft.PowerShell.Management
En ajoutant un astérisque également après le terme "Service" vous obtiendrez
des résultats supplémentaires, car ce sont des cmdlets qui auront un autre terme
avec "Service" dans le nom. Je vous laisse essayer pour voir.
Un autre moyen de trouver le nom d'une commande, je pense, moins efficace,
mais qui peut s'avérer utile rien que pour parcourir les commandes par curiosité,
c'est d'utiliser l'auto-complétion. Vous commencez à saisir un nom de commande,
par exemple "Get-" et vous appuyez ensuite sur "Tab" afin de faire défiler les
choix.
Note : l'utilisation de l'auto-complétion est indispensable pour être plus efficace
dans la saisie du code, mais aussi pour éviter les erreurs de frappe.
B. Obtenir de l'aide
Maintenant que l'on sait comment rechercher une commande, comment faire
pour l'utiliser ? De l'aide peut être obtenue, directement dans la console
PowerShell, en ligne sur Microsoft Docs voire même au sein de PowerShell
ISE.
On s'appuiera sur le commandlet "Get-Help", mais pour ma part j'utilise surtout la
documentation en ligne accessible depuis votre navigateur à l'adresse
suivante : Aide PowerShell - Microsoft Docs
Note : L'aide peut être actualisée avec la commande "Update-Help" afin d'avoir
une aide hors ligne et actualisée. En entreprise, sachez qu'il est possible
d'héberger l'aide sur un partage réseau afin de la distribuer via le réseau local,
plutôt que d'effectuer le téléchargement X fois.
Pour obtenir de l'aide sur le cmdlet "Get-Service" afin de savoir comment il
s'utilise, on exécute :
Get-Help Get-Service
Ce qui nous donne de l'aide directement dans la console :
Aperçu de la commande "Get-Help"
PSi l'on souhaite en savoir un peu plus et visualiser des exemples d'utilisation, on
ajoutera le paramètre "examples" comme ceci :
Get-Help Get-Service -examples
Pour finir sur l'aide, vous pouvez ajouter le paramètre "online" à la fin de la
commande pour que votre navigateur s'ouvre directement sur la page de l'aide
de ce cmdlet. Ce qui est bien pratique.
Get-Help Get-Service -online
C. Les alias
En plus de rencontrer des cmdlets classiques avec les noms approuvés par
Microsoft, vous allez surement rencontrer des noms de commandes basés sur des
alias. L'exemple le plus concret c'est les commandes DOS. En fait, la plupart des
commandes DOS fonctionnent dans la console PowerShell, comment ça se fait ?
Microsoft a intégré des alias pour faire une correspondance entre un
nom utilisé historiquement en DOS et renvoyé vers son équivalent en
PowerShell. Par exemple, si vous exécutez la commande "dir" qui permet de
lister le contenu d'un répertoire, vous n'allez pas exécuter la commande DOS,
mais directement "Get-ChildItem" qui est le cmdlet PowerShell qui assure
désormais cette fonction.
Remarque : Microsoft a intégré également des alias correspondants à des
commandes Unix, comme "ls" et "wget".
Il est possible de créer vos propres alias, mais ce n'est pas l'objet de cet article,
en attendant vous pouvez lister les alias existants avec "Get-Alias".
Aperçu de la liste d'alias obtenue avec Get-Alias
D. L'exécution des scripts
Lors de la première exécution d'un script sur une machine, vous pourriez être
déçu de constater que le script ne veut pas s'exécuter. Rassurez-vous, il s'agit
d'un comportement normal.
En effet, Windows intègre une politique de sécurité qui contrôle
l'exécution des scripts PowerShell. Pour des raisons de sécurité, elle est
configurée par défaut sur un mode restreint (Restricted) qui empêche l'exécution
des scripts PowerShell. Il y a plusieurs niveaux de protection, allant du niveau le
plus ouvert (Bypass) au niveau plus sécurisé où l'on exige qu'un script soit signé
(AllSigned) peu importe d'où ils proviennent (local ou internet).
Pour obtenir la stratégie actuellement appliquée sur votre machine, exécutez la
commande suivante :
Get-ExecutionPolicy
Pour pouvoir exécuter votre script, basculer la politique sur la valeur
"Unrestricted" comme ceci :
Set-ExecutionPolicy Unrestricted
Modification de la stratégie d'exécution
La stratégie d’exécution permet de vous prémunir contre les scripts que vous
jugez non fiables. En modifiant la stratégie d’exécution, vous vous exposez aux
risques de sécurité décrits dans la rubrique d’aide
about_Execution_Policies à l’adresse http://go.microsoft.com/fwlink/?
LinkID=135170. Voulez-vous modifier la stratégie
d’exécution ?
[O] Oui [T] Oui pour tout [N] Non [U] Non pour tout [S] Suspendre [?] Aide (la
valeur par défaut est « N ») : o
Vous êtes désormais en mesure d'exécuter des scripts PowerShell sur votre
machine.
Plus d'informations :
Documentation officielle : Set-ExecutionPolicy
Tutoriel : Modifier la stratégie d'exécution des scripts PowerShell
E. Une panoplie de modules
PowerShell est livré avec un ensemble de cmdlets, eux-mêmes associés à un
module c'est-à-dire à un ensemble de cmdlets. En parallèle, Microsoft propose
de nombreux modules officiels, comme par exemple un module Active
Directory qui contient un ensemble de cmdlets pour administrer un annuaire
Active Directory. On pourrait aussi citer des modules pour Office 365, la gestion
du firewall ou encore Hyper-V. En supplément, on trouvera également des
modules issus de la communauté PowerShell, généralement disponibles sur
GitHub directement.
Pour la gestion des modules, il y a quelques commandes à connaître :
Get-Module -ListAvailable : Vous permet de lister les modules disponibles en local
sur votre machine
Find-Module : Vous permet de rechercher un module parmi ceux référencés auprès
de Microsoft - Exemple : Find-Module *ActiveDirectory*
Install-Module <nom du module> : Vous permet d'installer un module sur votre
machine
En fait, installer un module revient à télécharger les fichiers sources et à les
positionner dans le bon dossier sur votre machine. Mais alors ces modules, où
sont-ils stockés ?
La variable d'environnement "PSModulePath" contient la liste des dossiers qui
sont scannés pour rechercher les modules PowerShell sur votre machine. Par
défaut, cette variable contient un répertoire personnel propre au profil de
l'utilisateur, ainsi qu'un répertoire dans "Program Files" et un autre dans le
répertoire Windows.
Vous pouvez consulter la valeur de cette variable avec la commande suivante :
$env:psmodulepath
Ce qui retourne par exemple :
C:\Users\Florian\Documents\WindowsPowerShell\Modules;C:\Program Files\
WindowsPowerShell\Modules;C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules
Puisque je parlais justement de variables, on va s'y atteler dans la partie suivante.
F. Jouer avec les variables
Les variables en PowerShell comme dans beaucoup d'autres langages se
déclarent en préfixant un mot du signe dollars "$". Pour déclarer une variable
"MaVariable" on indiquera simplement "$MaVariable". Chaque variable dispose
d'un type, comme "string" pour les chaînes de caractères, "int" pour les nombres
ou encore "boolean" pour un booléen.
Bien qu'il soit possible de forcer le type d'une variable, par défaut le type sera
attribué automatiquement en fonction de la forme des valeurs envoyées à la
variable. Par exemple, si l'on affecte une chaîne de caractères à une nouvelle
variable, elle prendra directement le type "string".
Exécutez le bout de code ci-dessous et vous obtiendrez le type de la variable
$MaVariable :
$MaVariable = "Hello World"
$MaVariable.GetType()
Ce qui retourne ceci :
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
On remarque la valeur "String" pour le nom du type de cette variable.
Remarque : Nous avons utilisé GetType() qui est une méthode c'est-à-dire une
action à effectuer sur la variable.
Comment concaténer la valeur de plusieurs variables ?
Imaginons deux variables qui contiennent une chaîne de caractères, que l'on
souhaite concaténer dans une seule et même variable. C'est tout simple, on
additionnera les deux variables comme on le ferait avec 2 nombres.
Voici un exemple :
$MaVariable1 = "Hello"
$MaVariable2 = "World"
$MaVariable3 = $MaVariable1 + $MaVariable2
$MaVariable3
La variable $MaVariable3 sera égale aux valeurs de $MaVariable1 et
$MaVariable2.
Maintenant, si l'on veut ajouter du texte en supplément, ou par exemple un
espace entre les deux mots, voici la syntaxe :
$MaVariable3 = $MaVariable1 + " " + $MaVariable2
$MaVariable3
Le fait d'indiquer $MaVariable3 permet tout simplement d'afficher le contenu de
la variable dans la console PowerShell.
Comment stocker le résultat d'une commande dans une variable ?
Rappelez-vous, le cmdlet "Get-Service" permet d'afficher la liste des services avec
l'état de chaque service. Si l'on souhaite stocker le résultat de cette commande
dans une variable, c'est simple !
$ServiceState = Get-Service
Ceci vous permet de stocker l'état des services à un instant t, on pourrait
imaginer comparer l'état des services à deux moments différents grâce à cette
méthode d'affectation dans une variable.
G. Le pipeline
Le pipeline est une notion indispensable que l'on utilise tellement souvent... Mais
d'ailleurs c'est quoi le pipeline ? Il s'agit de la barre verticale disponible sur la
touche "6" d'un clavier AZERTY : "|".
En PowerShell, le pipeline permet d'interconnecter différentes
commandes puisque la sortie d'une commande sera l'entrée de la
suivante.
Imaginons que l'on récupère la liste des services (Get-Service), mais que l'on
souhaite uniquement les services démarrés. Comment faire si la commande Get-
Service n'offre pas cette possibilité nativement ? On va faire un piping d'objet
pour filtrer le résultat dans une seconde commande.
Le cmdlet "Where-Object" permet de filtrer les données renvoyées par
un autre cmdlet. On va l'utiliser pour filtrer le résultat de la commande Get-
Service. On utilisera également $_ qui permet de cibler l'occurrence
courante renvoyée par la commande Get-Service (ou une autre commande,
selon celle qui est concernée par le pipeline).
Finalement, pour récupérer la liste des services en cours d'exécution, c'est-à-dire
le statut "running", on exécutera la commande suivante :
Get-Service | Where-Object{ $_.Status -eq "Running" }
Ci-dessus, "Status" correspond à une propriété de l'objet renvoyé par Get-Service,
le fait d'indiquer "$_.Status" permet de lire directement la valeur de cette
propriété, et ensuite on utilise l'opérateur de comparaison "eq" ("equal" -> "égal")
pour filtrer sur le statut "running".
Remarque : On utilise souvent des abréviations pour Where-Object : "Where" ou
même plus récemment "?"
IV. A la conquête de notre premier script
Maintenant que l'on a survolé différents points du scripting PowerShell, on va
pouvoir continuer l'apprentissage avec un premier script. En fait, il reste
énormément à apprendre, mais c'est sans fin ou presque... Il va falloir apprendre
au fur et à mesure.
Je vous propose de créer un script qui va surveiller les changements d'état de
services Windows. Dans le cadre de cet exemple, on va forcer un peu les choses
pour simuler des changements d'état sur deux services.
On a vu précédemment que la commande "Get-Service | Where-Object{ $_.Status
-eq "Running" }" permet d'obtenir la liste des services en cours d'exécution, on va
donc stocker cet état dans une variable : $ServiceStateBefore.
$ServiceStateBefore = Get-Service | Where-Object{ $_.Status -eq "Running" }
Ensuite, on va simuler deux changements d'état : Stopper le service Windows
Update (wuauserv) et démarrer le service de temps (w32time) :
# On stoppe le service Windows Update
Stop-Service -Name wuauserv
# On démarre le service de temps
Start-Service -Name W32Time
Puis on va de nouveau stocker l'état des services dans une seconde variable
$ServiceStateAfter :
$ServiceStateAfter = Get-Service | Where-Object{ $_.Status -eq "Running" }
A cet instant, on dispose de deux variables qui stockent l'état des services à deux
instants différents. On va comparer ces deux objets afin de détecter les
changements.
Pour réaliser cette opération, nous allons utiliser le cmdlet Compare-Object qui
permet de comparer des objets entre eux, ce qui peut être utile dans de multiple
cas, notamment pour comparer deux fichiers.
Compare-Object $ServiceStateBefore $ServiceStateAfter -Property Name,Status
On va lui indiquer les deux objets en entrée, à
savoir $ServiceStateBefore et $ServiceStateAfter. Puis, on indique les propriétés à
comparer pour détecter les changements, on va utiliser le nom (Name) et le
statut (Status).
Enfin, on terminera par l'ajout de deux commandes pour remettre à l'état initial
les services :
# Retour à l'état initial
Start-Service -Name wuauserv
Stop-Service -Name W32Time
Ce qui nous donne le script suivant :
$ServiceStateBefore = Get-Service | Where-Object{ $_.Status -eq "Running" }
# On stoppe le service Windows Update
Stop-Service -Name wuauserv
# On démarre le service de temps
Start-Service -Name W32Time
$ServiceStateAfter = Get-Service | Where-Object{ $_.Status -eq "Running" }
Compare-Object $ServiceStateBefore $ServiceStateAfter -Property Name,Status
# Retour à l'état initial
Start-Service -Name wuauserv
Stop-Service -Name W32Time
Si vous exécutez le script sur votre machine, vous obtiendrez le retour suivant :
Pour interpréter ce résultat, c'est relativement simple. La propriété "SideIndicator"
indique pour chaque ligne de quel côté une modification a été détectée. Le signe
"=>" indique le service tournait dans $ServiceStateBefore, mais qu'il est
introuvable dans $ServiceStateAfter, ce qui est logique, car W32Time s'est arrêté.
A l'inverse, le signe "<=" indique que le service tournait dans $ServiceStateAfter,
mais pas dans $ServiceStateBefore, ce qui est logique, car on a démarré le
service "wuauserv" entre temps.
Voilà pour ce qui est d'un premier script, qui pourrait être amélioré, mais
n'oublions pas que l'objectif est de faire ses premiers pas avec PowerShell 🙂
V. Interroger l'annuaire Active Directory
en PowerShell
Pour terminer cette initiation, on va interroger un annuaire Active Directory en
PowerShell, car comme je le disais en introduction, c'est une utilisation très
fréquente. L'objectif est de manipuler quelques cmdlets, notamment pour
rechercher des objets dans l'annuaire.
On va commencer par importer le module Active Directory, d'ailleurs avec les
versions récentes de PowerShell l'importation sera réalisée automatiquement si la
ligne n'est pas spécifiée, mais que vous utilisez un cmdlet d'un module externe.
Import-Module ActiveDirectory
On peut rechercher un utilisateur avec le cmdlet "Get-ADUser". Pour lister
l'ensemble des cmdlets du module Active Directory, vous pouvez utiliser la
commande suivante :
Get-Command -Module ActiveDirectory
Pour la recherche d'un utilisateur, il suffira d'utiliser le paramètre "Filter" pour
affiner la recherche. En s'appuyant sur la propriété SamAccountName c'est-à-dire
le login, on va pouvoir rechercher l'utilisateur "florian.burnel" :
Get-ADUser -Filter "SamAccountName -eq 'florian.burnel'"
A la place de l'opérateur de comparaison "eq" on pourrait en utiliser d'autres,
comme "like" pour trouver les utilisateurs qui contiennent le mot recherché.
Remarque : On aurait pu se passer du filtre pour ajouter un pipeline suivi
de Where-Object pour rechercher notre utilisateur, mais ce sera plus gourmand
en ressources et donc moins performant. C'est logique, car sans filtre, le
cmdlet Get-ADUser va récupérer la liste de tous les utilisateurs et dans un second
temps le Where-Object va filtrer les résultats, alors que via le
paramètre Filter permet de filtrer directement.
Et comme PowerShell est un langage très flexible, il y a bien souvent plusieurs
manières de parvenir à ses fins. Pour la recherche de notre utilisateur, on aurait
pu utiliser le cmdlet "Search-ADAccount".
Ce cmdlet est très intéressant et contient plusieurs paramètres qui permettent
d'effectuer des recherches rapides sur l'annuaire ; par exemple on peut
rechercher les comptes utilisateurs désactivés facilement :
Search-ADAccount -AccountDisabled -UsersOnly
Pour terminer, voici ce que je vous propose : réaliser un export au format CSV de
la liste des utilisateurs avec les informations suivantes : login, SID (identifiant
unique), date de création de l'utilisateur et le nombre de connexions.
Tout d'abord, il faut bien connaître les attributs Active Directory, correspondant à
ces informations. La console historique "Utilisateurs et ordinateurs Active
Directory" vous permettra d'obtenir facilement la liste des attributs.
Pour les champs que nous souhaitons, ça donne :
Login = SamAccountName
Identifiant unique = SID (ou ObjectSID)
Date de création = whenCreated
Nombre de connexions = logonCount
Par défaut, lorsque l'on exécute la commande Get-ADUser toutes les propriétés
d'un objet ne sont pas sélectionnées pour des raisons de performances. Pour
sélectionner des propriétés supplémentaires, on va utiliser le paramètre
"Properties", ce qui nous donne :
Get-ADUser -Filter * -Properties SamAccountName, SID, whenCreated, logonCount
Vous remarquerez que l'on utilise * comme filtre, afin de prendre tous les
utilisateurs. Le paramètre "Filter" est obligatoire. Maintenant, on va utiliser le
pipeline pour affiner l'objet de sortie avec le cmdlet Select-Object qui va
permettre de sélectionner uniquement les 4 propriétés qui nous intéressent pour
l'export CSV, sinon on aurait beaucoup plus d'infos qu'on le souhaite.
Ce qui donne :
Get-ADUser -Filter * -Properties SamAccountName, SID, whenCreated, logonCount |
Select-Object SamAccountName, SID, whenCreated, logonCount
La dernière étape consiste à exporter au format CSV les données, on va
utiliser le cmdlet "Export-Csv". Nous allons utiliser trois
paramètres : Path pour le chemin vers le fichier CSV de sortie, Encoding pour
l'encodage des données en UTF-8 (pour gérer les accents) et le paramètre
"NoTypeInformation" pour supprimer les infos sur le type dans le fichier.
Voici la commande complète :
Get-ADUser -Filter * -Properties SamAccountName, SID, whenCreated, logonCount |
Select-Object SamAccountName, SID, whenCreated, logonCount | Export-Csv -Path
"C:\export.csv" -NoTypeInformation -Encoding UTF8
Suite à l'export, vous allez obtenir un fichier CSV qui aura du contenu sous cette
forme :
"SamAccountName","SID","whenCreated","logonCount"
"user01","S-1-5-21-2077788776-554437559-1112223334-11784","22/02/2016
11:35:14","27"
"user02","S-1-5-21-2077788776-554437559-1112223334-11778","22/02/2016
11:35:05","30"
"user03","S-1-5-21-2077788776-554437559-1112223334-11785","22/02/2016
11:35:16","10"
Maintenant que l'on a notre CSV en main, on peut exploiter ces données très
facilement, avec Excel notamment.
Voilà, je vais m'arrêter là, car on pourrait en écrire des pages et des pages... Ça
vous donne un aperçu de ce que l'on peut faire en PowerShell avec l'Active
Directory, mais ce n'est vraiment qu'un aperçu. 🙂
VI. Et ensuite ?
Ce tutoriel touche à sa fin, j'espère qu'il vous sera utile pour vous initier au
scripting Powershell, maintenant vous allez devoir vous familiariser avec ces
nouvelles notions et ensuite poursuivre votre apprentissage. Pour cela, je vous
propose quelques ressources :
PowerShell pour les débutants (en 4 parties)
Analyser la qualité de son code PowerShell
Obtenir des informations sur l'OS en PowerShell
Tutoriels PowerShell sur IT-Connect
Par ailleurs, vous pouvez lire du code afin de progresser en essayant de le
comprendre et afin d'assimiler les syntaxes les plus courantes. Faire un tour sur
Github est un excellent moyen de trouver du code. Par exemple, vous en
trouverez quelques-uns sur mon Github ou sur celui de LazyWinAdmin.
Enfin, retrouvez sur Microsoft Virtual Academy un cours vidéo gratuit
d'introduction à PowerShell, le tout en français.
Bon courage ! 🙂
15 commandes indispensables pour
débuter avec PowerShell
30/03/2021 Florian Burnel 5 Commentaires Powershell, Scripting
Sommaire [-]
I. Présentation
II. PowerShell : 15 commandes indispensables
o A. Get-Command
o B. Get-Help
o C. Get-Member
o D. Get-Process
o E. Get-Service
o F. Get-PSDrive
o G. Get-Content
o H. Get-ChildItem
o I. Set-Location
o J. Get-Item
o K. New-Item
o L. Remove-Item
o M. Get-Date
o N. Test-Path
o O. Test-Connection
III. Comment créer son premier script PowerShell ?
I. Présentation
Dans ce nouvel article, je vais vous présenter 15 commandes PowerShell
qu'il est indispensable de connaître pour débuter ! Cet article est dans la
continuité de celui qui s'intitule "Comment créer son premier script
PowerShell ?".
Tutoriel à suivre au format vidéo :
Ces commandes sont à connaître pour débuter sereinement, car elles sont
incontournables, et par expérience, je sais qu'on les utilise fréquemment.
Je ne vais pas être exhaustif sur toutes les possibilités de chaque commande pour
ne pas rendre l'article imbuvable, le but étant de vous faire une première
initiation pratique pour chaque commande. Des liens supplémentaires seront
ajoutés vers d'autres articles et vidéos pour vous permettre d'approfondir.
II. PowerShell : 15 commandes
indispensables
A. Get-Command
La commande Get-Command a pour objectif de vous aider à trouver une
commande qui correspond à vos besoins. Sans aucun paramètre, elle retourne
l'intégralité des commandes disponibles sur une machine :
Get-Command
Ce qui donne lieu à une sortie, forcément, conséquente et pas très exploitable.
Avant d'aller plus loin, un petit rappel sur la manière dont est constitué le nom
d'une commande Powershell :
<Verbe>-<Nom>
La première partie est un verbe (Get, Set, Remove, etc...) et la deuxième
partie est un nom pour désigner quelque chose (Service, Process,
ADUser, ADGroup, etc.).
La commande Get-Command va permettre de rechercher une commande en
filtrant par rapport au verbe, au nom ou à l'intégralité du nom de la
commande. C'est plus intéressant si l'on affine la recherche.
Pour obtenir toutes les commandes disponibles sur votre machine et qui
commencent par le verbe "New", on utilisera :
Get-Command -Verb New
Ensuite, prenons un autre cas, par exemple, pour trouver toutes les commandes
qui ont le nom "Services", on utilisera :
Get-Command -Noun Service
Ainsi, on obtient facilement la liste des commandes qui vont permettre de
manipuler les services. Comme les verbes sont explicites, on peut facilement
deviner que par exemple, la commande Start-Service sert à démarrer un
service. Quelques notions de base en anglais pour connaître les mots de base,
c'est forcément un plus...
Si l'on veut plutôt obtenir toutes les commandes qui ont le mot "service" dans le
nom, on utilisera le paramètre -Name à la place de -Noun, avec la notion de
wildcard "*" :
Get-Command -Name *Service*
On peut voir dans la sortie ci-dessous que des applications sont également
présentes dans les résultats.
En fait, les paramètres -Noun, -Name et -Verb supportent le wildcard. On aurait
pu conserver -Noun sans le remplacer par -Name, ce qui donne :
Get-Command -Noun *Service*
La commande ci-dessus va donner la même sortie qu'avec -Name à l'exception
qu'il n'y aura pas les applications dans les résultats.
Il faut savoir que l'on peut toujours filtrer un peu plus les résultats. Par exemple,
on peut afficher seulement les commandes du type "Cmdlet" :
Get-Command -Name *Service* -CommandType Cmdlet
Enfin, on peut obtenir la liste de toutes les commandes d'un module spécifique.
Par exemple, toutes les commandes du module Active Directory :
Get-Command -Module ActiveDirectory
Vous l'aurez compris, le cmdlet Get-Command est très pratique pour
rechercher une commande par soi-même ! ?
B. Get-Help
Une fois que l'on a repéré la commande qui nous intéresse grâce à Get-
Command ou une autre méthode, on va en toute logique se poser la question
suivante : comment s'utilise cette commande PowerShell ? C'est là
qu'intervient le cmdlet "Get-Help" puisqu'il permet d'obtenir de l'aide.
Note : avant d'utiliser Get-Help pour la première fois, je vous recommande
d'ouvrir une console PowerShell en tant qu'administrateur et d'exécuter la
commande Update-Help pour mettre à jour l'aide locale.
Prenons l'exemple du cmdlet "Start-Service" évoqué précédemment (et choisi au
hasard en fait) :
Get-Help Start-Service
De base, la commande retourne une synthèse de l'aide. Si l'on veut obtenir des
exemples d'utilisation de la commande, nous devons faire :
Get-Help Start-Service -Examples
On remarque que la commande Start-Service dispose d'un paramètre nommé -
Name. Si l'on veut en savoir plus sur ce paramètre, on peut consulter l'aide de
cette façon :
Get-Help Start-Service -Parameter Name
L'accès complet à l'aide est possible grâce au paramètre -Full où l'on aura la
description de la commande, le détail de chaque paramètre, les exemples, etc.
Get-Help Start-Service -Full
La console PowerShell peut vous rediriger directement sur la page d'aide en ligne
correspondante à la commande que vous souhaitez. Cela est possible grâce au
paramètre -Online :
Get-Help Start-Service -Online
Get-Help est une commande à connaître et personnellement, si j'ai un
accès à Internet je privilégie l'utilisation de l'aide en ligne sur le site de
Microsoft.
Pour finir sur l'aide, je vous livre une dernière astuce qui consiste à utiliser la
fonction "help". Elle fonctionne sur le même principe et permet d'utiliser
facilement Out-GridView pour avoir une sortie en mode graphique.
Voyez par vous-même en essayant la commande ci-dessous :
help Start-Service -Full | Out-GridView
C. Get-Member
Pour explorer une commande, il y a le cmdlet "Get-Member" et son alias "gm" qui
sont à connaître. Cette commande va permettre d'obtenir tous les membres d'une
commande, c'est-à-dire toutes les propriétés et méthodes d'une
commande.
Cette commande s'utilise de cette façon :
<commande source> | Get-Member
Ou
<commande source> | gm
La commande source sera une commande complète ou incomplète, c'est-à-dire
seulement un nom de commande ou un nom de commande avec des paramètres
et valeurs. Pour que ce soit plus parlant :
Get-Service | Get-Member
ou
Get-Service -Name wuauserv | Get-Member
Le résultat renvoyé par Get-Member pourra varier en fonction de la commande
source, même pour un même cmdlet, en fonction des paramètres utilisés.
Sur la copie d'écran ci-dessus, on peut voir une liste de méthode (actions)
que l'on peut utiliser, ainsi que des propriétés (valeurs). Par exemple, la
méthode "Stop()" permettra d'arrêter un service en utilisant Get-Service. À titre
d'information, voici comment l'utiliser pour arrêter un service :
(Get-Service -Name wuauserv).stop()
De la même manière, on peut afficher les valeurs des propriétés que l'on
souhaite. Pour cela, on peut utiliser Format-List, Format-Table ou encore Select-
Object. Voici un exemple où j'ai sélectionné quelques propriétés de Get-Service
retournée par Get-Member :
Get-Service -Name wuauserv | Format-Table Status, StartType, MachineName,
DisplayName
Les commandes Get-Command et Get-Help sont très utiles pour débuter et moins
par la suite quand on maîtrise un bon nombre de commandes. Même si on les
réutilise souvent, finalement. Par contre, la commande Get-Member est utile
"tout le temps" pour explorer les méthodes et propriétés des
commandes, car c'est très vaste.
D. Get-Process
Lorsqu'il s'agit de récupérer la liste des processus actifs sur une machine, on
s'oriente naturellement vers le Gestionnaire des tâches, car il affiche en temps
réel la liste des processus actifs avec différentes informations :
La commande Get-Process va permettre de faire la même chose, à l'aide de
PowerShell, son exécution sans paramètre va lister les processus actifs à
l'instant t :
Dans la sortie ci-dessus, le nom des colonnes sont des alias vers d'autres noms de
propriétés. La commande Get-Member que l'on a vu précédemment permet
d'obtenir cette information :
Name MemberType Definition
---- ---------- ----------
Handles AliasProperty Handles = Handlecount
Name AliasProperty Name = ProcessName
NPM AliasProperty NPM = NonpagedSystemMemorySize64
PM AliasProperty PM = PagedMemorySize64
SI AliasProperty SI = SessionId
VM AliasProperty VM = VirtualMemorySize64
WS AliasProperty WS = WorkingSet64
Pour avoir une sortie qui se rapproche réellement du Gestionnaire des tâches, et
notamment avoir le nom de l'utilisateur qui est à l'origine de l'exécution du
processus, on va ajouter le paramètre -IncludeUserName
Get-Process -IncludeUserName
La colonne WS correspond à WorkingSet, ce qui indique en fait la consommation
en RAM de ce processus, ici en Mégaoctets. Tandis que la colonne CPU indique le
temps d'utilisation du processeur.
Avec la commande initiale (sans -IncludeUserName), la valeur est en octet. Ainsi,
pour obtenir la liste de tous les processus qui consomment au minimum 100 Mo
de RAM, on utilisera la valeur "100000000".
Get-Process | Where-Object { $_.WorkingSet -ge 100000000 }
Si l'on recherche un processus spécifique en cours d'exécution, en lien avec un
logiciel, par exemple le navigateur Chrome et son processus "chrome", on peut
affiner la commande :
Get-Process -Name "chrome" -IncludeUserName
Ou, tout simplement :
Get-Process -Name "chrome"
La liste des propriétés disponibles avec la commande Get-Process est très longue.
On peut, par exemple, obtenir la date de création de chaque processus grâce à la
propriété StartTime.
Get-Process | Format-Table Name, StartTime
E. Get-Service
Grâce à la commande Get-Service, nous allons pouvoir récupérer des
informations sur les services présents sur la machine, ainsi que sur leur état et
leur type de démarrage : utile pour vérifier si un service est en cours d'exécution
ou pour lister tous les services en cours d'exécution. Une commande que l'on peut
utiliser pour créer un script de supervision, par exemple.
Sans paramètre, la commande va renvoyer tous les services avec plusieurs
informations : le statut, le nom du service et son nom d'affichage (tel qu'il est
dans la console de gestion des services).
Get-Service
Pour récupérer la liste de tous les services en cours d'exécution, on doit
effectuer un filtre avec Where car il n'y a pas de paramètres directement au sein
de Get-Service pour réaliser ce filtre. Le statut qui nous intéresse est "Running",
car il correspond à l'état "En cours d'exécution".
Get-Service | Where-Object {$_.status -eq "Running"}
Enfin, pour obtenir l'état d'un statut spécifique, par exemple le service "Windows
Update" (qui a pour nom wuauserv), on pourra le cibler directement :
Get-Service -Name "wuauserv"
PowerShell contient des commandes supplémentaires pour gérer les services,
notamment pour arrêter un service (Stop-Service) ou démarrer un service (Start-
Service).
⭐ Guide complet sur l'utilisation de Get-Service
F. Get-PSDrive
La commande Get-PSDrive permet de récupérer des informations sur les
différents lecteurs du système. Plusieurs types de lecteurs différents sont
remontés par cette commande, et il y en a deux particulièrement utiles :
Les lecteurs de type "FileSystem" correspondant à vos volumes montés sur votre
système, par exemple le volume "C" où Windows est installé, ou alors un lecteur
réseau connecté sur votre machine.
Les lecteurs de type "Registry" correspondent au Registre Windows, en l'occurrence
les ruches HKCU et HKLM
Pour chaque lecteur, on obtient son nom, sa racine, ainsi que l'espace utilisé et
l'espace libre lorsqu'il s'agit d'un espace de stockage. Il suffit d'exécuter la
commande sans aucun paramètre pour obtenir cette synthèse :
Get-PSDrive
Pour obtenir des informations seulement sur les lecteurs du fournisseur (Provider)
"FileSystem", c'est-à-dire les espaces de stockage, on utilisera cette commande :
Get-PSDrive -PSProvider FileSystem
G. Get-Content
La commande Get-Content sert à récupérer le contenu d'un fichier, simplement
pour l'afficher ou pour l'exploiter dans un script complet. Son utilisation est simple
puisqu'il suffit de spécifier le nom d'un fichier à charger :
Get-Content -Path "<chemin-du-fichier>"
Get-Content -Path "C:\TEMP\Pays.txt"
La commande ci-dessus va récupérer l'intégralité du fichier.
Pour récupérer les premières lignes d'un fichier, on va utiliser le paramètre -
TotalCount suivi du nombre de lignes à récupérer, en partant du début :
Get-Content "C:\TEMP\Pays.txt" -TotalCount 5
Enfin, pour récupérer les dernières lignes d'un fichier, on va utiliser le paramètre -
Tail suivi du nombre de lignes à récupérer, en partant de la fin :
Get-Content "C:\TEMP\Pays.txt" -Tail 5
⭐ Guide complet sur l'utilisation de Get-Content
H. Get-ChildItem
La commande Get-ChildItem (et son alias gci) permet de lister le contenu
d'un dossier en PowerShell. On peut lister le contenu d'un dossier spécifique
en s'arrêtant au dossier cible, mais on peut aussi lister le contenu de façon
récursive : le dossier cible ainsi que le contenu de tout ses sous-dossiers.
Si l'on exécute la commande Get-ChildItem dans une console, le contenu du
répertoire dans lequel on se situe sera listé. Sinon, on peut préciser le chemin
vers un dossier grâce à -Path :
Get-ChildItem -Path "C:\TEMP"
Pour ajouter de la récursivité (prendre en compte les sous-dossiers), nous devrons
ajouter -Recurse, comme ceci :
Get-ChildItem -Path "C:\TEMP" -Recurse
On peut aussi lister seulement les fichiers avec -File ou seulement les dossiers
avec -Directory :
Get-ChildItem -Directory
Ce cmdlet intègre trois paramètres particulièrement intéressants pour filtrer les
résultats : -Filter, -Include et -Exclude.
Ainsi, pour récupérer la liste de tous les fichiers PDF contenus dans un dossier,
nous pouvons faire :
Get-ChildItem -Path "C:\TEMP" -Filter "*.pdf"
Dans le même esprit, on peut exclure des résultats tous les fichiers JPG :
Get-ChildItem -Exclude *.jpg
Pour filtrer sur plusieurs extensions de fichiers, je vous propose d'utiliser -Include.
Il s'utilise simplement, mais il y a une petite subtilité : il faut indiquer un wildcard
à la fin du chemin pour bien préciser que l'on filtre le contenu du dossier, sinon, le
résultat sera vide à chaque fois. Voici comment récupérer seulement les fichiers
EXE et PDF :
Get-ChildItem "C:\TEMP\*" -Include *.exe,*.pdf
Enfin, sachez que Get-ChildItem sert également à lister le contenu du Registre
Windows. Par exemple, la ruche HKLM correspondante à HKEY_LOCAL_MACHINE :
Get-ChildItem -Path HKLM:\SYSTEM
⭐ Cas d'usage : comment lister les dossiers vides en PowerShell ?
I. Set-Location
Utile pour l'usage de la console PowerShell plus que pour les scripts directement,
la commande Set-Location est indispensable, car elle permet de se déplacer d'un
dossier à un autre. Autrement dit, elle correspond à la fameuse commande "cd"
(Change Directory) que l'on retrouve aussi sous Linux.
Par exemple, si l'on est dans le dossier "C:\Users" et que l'on veut se positionner
dans le dossier "C:\TEMP", on fera tout simplement :
Set-Location "C:\TEMP"
Le chemin que l'on indique sera automatiquement associé au paramètre -Path.
J. Get-Item
Get-Item est un peu dans le même esprit que Get-ChildItem sauf qu'il sert
à récupérer des informations sur un élément précis, notamment un
dossier ou un fichier. Finalement, on peut aussi lister le contenu d'un dossier
courant grâce à la commande ci-dessous :
Get-Item *
Le fait d'indiquer le wildcard "*" permet de lister tous les éléments. L'idée, c'est
plutôt de cibler un fichier comme dans cet exemple avec "Teams.ps1" :
Get-Item "C:\TEMP\Teams.ps1"
Ensuite, on va lire les propriétés de cet objet, ce qui va permettre d'obtenir plein
d'informations pertinentes : nom, date de création, date de dernier accès,
date de dernière modification. Ce qui se traduit par la commande suivante :
Get-Item "C:\TEMP\Teams.ps1" | Select-Object Name, CreationTime,
LastAccessTime, LastWriteTime
Je ne veux pas aller trop loin, mais on peut coupler l'utilisation de Get-ChildItem et
Get-Item pour obtenir les mêmes informations par rapport à une liste de fichiers
que l'on obtient via Get-ChildItem. Avec un filtre sur les fichiers EXE, cela donne :
Get-ChildItem -Filter *.exe | Get-Item | Select-Object Name, CreationTime,
LastAccessTime, LastWriteTime
Même si, on peut faire la même chose avec Get-Item (comme souvent il y a
plusieurs façons de faire) :
Get-Item *.exe | Select-Object Name, CreationTime, LastAccessTime,
LastWriteTime
Pour réaliser du reporting ou de la surveillance sur des éléments, la
commande Get-Item est redoutable !
K. New-Item
La création d'un dossier ou d'un fichier passe par l'utilisation de la
commande New-Item. Cette commande sert aussi à créer des liens
symboliques. Tout se joue au sein du paramètre -ItemType, alors que le
paramètre -Path sert à préciser le chemin de l'élément et -Name son nom.
Commençons par créer un dossier nommé "POWERSHELL" dans le dossier "C:\
TEMP" :
New-Item -Path "C:\TEMP\PS" -Name "POWERSHELL" -ItemType Directory
Déplaçons-nous dans ce dossier avec Set-Location (vu précédemment) et créons
un nouveau fichier TXT :
Set-Location C:\TEMP\PS\POWERSHELL
New-Item -Path . -Name "IT-Connect.txt" -ItemType File
La commande ci-dessus contient la valeur "." pour le chemin (-Path), ce qui
permet de spécifier le dossier courant. On pourrait même créer plusieurs fichiers
en même temps, par exemple un fichier "fichier1.txt" et "fichier2.txt" dans notre
dossier créé précédemment :
New-Item -ItemType File -Path "C:\TEMP\PS\POWERSHELL\FICHIER1.TXT", "C:\TEMP\
PS\POWERSHELL\FICHIER2.TXT"
L. Remove-Item
À l'inverse de la commande précédente, Remove-Item sert à supprimer
un élément, que ce soit un fichier ou un dossier.
Pour supprimer un fichier, c'est tout simple, on spécifie son nom :
Remove-Item .\logiciel.exe
Pour supprimer un dossier ainsi que tout son contenu, y compris s'il a des sous-
dossiers (à manipuler avec précaution), on utilisera en complément les
paramètres -Recurse et -Force :
Remove-Item "C:\TEMP\DossierCible\ -Recurse -Force
Enfin, je vous propose un dernier exemple : supprimer tous les fichiers JPG qui se
trouvent dans un dossier :
Remove-Item "C:\TEMP\PS\*" -Include *.jpg
Cette commande est souvent couplée à l'utilisation de Get-ChildItem comme
avec Get-Item, et elle sert aussi à supprimer des éléments dans le registre.
M. Get-Date
La commande Get-Date sert à récupérer la date et l'heure, sous différents
formats. Très utile dans les scripts, notamment pour la gestion de fichiers de logs,
mais aussi pour comparer des dates.
Get-Date
On peut obtenir la date sous la forme "AnnéeMoisJour" :
Get-Date -Format "yyyyMMdd"
20210319
De la même façon, en modifiant l'ordre et en ajoutant un "/" entre chaque partie :
Get-Date -Format "dd/MM/yyyy"
19/03/2021
Enfin, on pourrait inclure à la fin l'heure :
Get-Date -Format "yyyyMMdd_hhmm"
20210326_1131
Le fait d'utiliser "hh" donne l'heure sur 12 heures (am/pm) alors que "HH", en
majuscules donc, donne l'heure au format 24 heures.
Pour en savoir plus sur l'utilisation de ce cmdlet :
⭐ Guide complet sur l'utilisation de Get-Date
N. Test-Path
Le cmdlet Test-Path sert à tester l'existence d'un élément, généralement un
fichier ou un dossier. Par exemple pour tester l'existence du chemin "C:\TEMP", on
exécutera :
Test-Path -Path "C:\TEMP"
La commande ne retournera pas le contenu du dossier ou ses propriétés,
simplement une valeur booléenne : vraie ou faux. Simple, mais tellement pratique
!
Comme je l'explique dans l'article dédié à Test-Path (voir lien ci-dessous), on peut
tester l'existence d'un fichier et sa date de dernière modification, pour voir si elle
est "plus récente que" (NewerThan) ou "plus ancienne que" (OlderThan) en
précisant une date.
⭐ PowerShell : le guide pour utiliser Test-Path
O. Test-Connection
Pour finir, je souhaitais vous parler de Test-Connection : l'équivalent de l'éternelle
commande "ping", mais à la façon de PowerShell. Pour réaliser 4 pings à
destination d'une machine, on peut spécifier son adresse IP ou son nom DNS :
Test-Connection 1.1.1.1
Si l'on veut réaliser seulement 1 ping, ce qui est pratique pour simplement tester
la connectivité vers une machine, on utilisera -Count suivi du nombre de ping à
réaliser :
Test-Connection 1.1.1.1 -Count 1
À l'inverse, si l'on veut que le ping soit continue et qu'il ne s'arrête pas
automatiquement, on précisera -Continuous :
Test-Connection 1.1.1.1 -Continuous
Enfin, on peut facilement tester plusieurs hôtes : il suffit de séparer les cibles par
une virgule :
Test-Connection 1.1.1.1, www.google.fr -Count 1
L'outil tracert qui permet de déterminer l'itinéraire jusqu'à un hôte distant est
repris par Test-Connection. Il suffit de préciser le paramètre -Traceroute :
Test-Connection www.google.fr -Traceroute
⭐ A découvrir aussi pour tester des ports: Test-NetConnection
Get-Content : comment lire le contenu
d’un fichier en PowerShell ?
02/03/2021 Florian Burnel Aucun commentaire Powershell, Scripting
Sommaire [-]
I. Présentation
II. Lire simplement le contenu d'un fichier
III. Le tail de Linux à la mode PowerShell
IV. Récupérer les X premières lignes d'un fichier
V. NTFS : consulter un stream secret dans un fichier
I. Présentation
Le cmdlet Get-Content fait partie des commandes incontournables lorsque l'on
s'intéresse au scripting PowerShell. Il va permettre de lire le contenu d'un
fichier en PowerShell, ce qui est une action très courante. En plus de lire les
données, on va pouvoir importer les données dans une variable pour les exploiter
dans le script PowerShell. On peut utiliser Get-Content pour récupérer le contenu
d'un fichier de log, par exemple.
Nous verrons que Get-Content est un cmdlet puissant qui est capable de faire
plus que simplement récupérer le contenu d'un fichier intégralement, d'où
l'intérêt de lui dédier un article complet. Ce cmdlet fonctionne sous Windows
Powershell 5.1 et PowerShell, notamment dans la dernière version à ce jour :
PowerShell 7.1.1.
? Tutoriel disponible au format vidéo :
II. Lire simplement le contenu d'un
fichier
Pour commencer, on va simplement lire le contenu d'un fichier texte qui
contiendra une liste de valeurs. Pour suivre ce tutoriel, je vous invite à créer un
fichier nommé "Pays.txt" et stocké dans "C:\TEMP". Ce fichier doit avoir le contenu
suivant :
France
Costa Rica
Belgique
Suisse
Espagne
Colombie
Canada
Brésil
Islande
Nicaragua
Pour lire et afficher dans la console le contenu de ce fichier, la commande est
super simple puisqu'il suffit de préciser le nom du fichier (ou le chemin complet
s'il n'est pas dans le répertoire courant) :
Get-Content "C:\TEMP\Pays.txt"
Le paramètre -Path sera utilisé de manière implicite pour cette valeur. Si l'on écrit
la commande ci-dessous, cela revient au même.
Get-Content -Path "C:\TEMP\Pays.txt"
Afficher le contenu dans la console ne donne pas grand-chose. C'est plus
intéressant quand on va stocker le contenu du fichier dans une variable dans le
but de l'exploiter. Il suffit de créer une variable, par exemple $Pays, et de lui
attribuer le contenu du fichier comme valeur :
$Pays = Get-Content "C:\TEMP\Pays.txt"
Par curiosité, on peut regarder le type de la variable $Pays après lui avoir attribué
une valeur :
$Pays.GetType()
On peut voir que l'on obtient deux informations pertinentes : "Object[]" et
"System.Array". Nous avons affaire à un objet sous la forme d'un tableau de
valeurs ; c'est intéressant ! ?
Pour compter le nombre d'éléments dans ce fichier texte, on peut le faire de deux
façons différentes :
$Pays.Count
($Pays | Measure-Object).Count
Nous avons 10 éléments, puisqu'il s'agit d'un tableau la première valeur
correspond à l'index 0 et la dernière à l'index 9 (puisque l'on a seulement
10 éléments). Ainsi, la valeur à l'index 0 sera "France" et celle à l'index 9 sera
Nicaragua.
Si l'on veut consulter la valeur située en index 0, c'est-à-dire la première valeur,
c'est tout simple :
$Pays[0]
Ou si vous préférez, cela revient à faire :
(Get-Content "C:\TEMP\Pays.txt")[0]
Dans le même esprit, pour récupérer la dernière valeur sans connaître le numéro
d'index exact, il y a une astuce ! Il suffit d'utiliser "-1" comme numéro pour l'index
:
(Get-Content "C:\TEMP\Pays.txt")[-1]
Au lieu de récupérer le contenu du fichier sous la forme d'un tableau, on peut le
récupérer comme une seule chaîne de caractères. Il suffit d'ajouter le paramètre -
Raw à la commande :
Get-Content -Path "C:\TEMP\Pays.txt" -Raw
Passons à la suite avec quelques exemples pratiques.
III. Le tail de Linux à la mode PowerShell
Sous Linux, il est très fréquent d'utiliser la commande tail pour afficher les
dernières lignes d'un fichier. Bien souvent, je l'utilise pour consulter un fichier
de log, d'autant plus que la sortie est dynamique : si des lignes sont ajoutées au
fichier, elles s'afficheront dans la console au fur et à mesure.
C'est très pratique et c'est possible de faire la même chose en PowerShell, à l'aide
de Get-Content et d'une option qui se nomme... -Tail et d'une deuxième option -
Wait ! ?
Sans l'option -Wait, on peut récupérer les X dernières lignes d'un fichier en
utilisant -Tail tout seul. Par exemple, pour récupérer les 5 dernières lignes de
notre fichier Pays.txt :
Get-Content "C:\TEMP\Pays.txt" -Tail 5
Maintenant, si l'on veut afficher les 5 dernières lignes et attendre pour récupérer
les futures lignes ajoutées au fichier, on va utiliser cette syntaxe :
Get-Content "C:\TEMP\Pays.txt" -Tail 5 -Wait
Pour faire le test, exécutez la commande ci-dessus puis modifiez le fichier
"Pays.txt" pour ajouter une ligne : vous verrez qu'elle s'affiche quasiment en
temps réel dans la console PowerShell où la commande tourne ?.
En fait, grâce à la commande -Wait, Get-Content maintient le fichier ouvert et
vérifie chaque seconde s'il y a du nouveau contenu à afficher. Pour terminer
l'exécution de la commande, c'est tout simple, il suffit d'effectuer un "CTRL + C".
Il est à noter que vous pouvez utiliser l'option -Wait seule : dans ce cas, le
fichier va s'afficher en intégralité dans la console et ensuite il va rester en attente.
Get-Content "C:\TEMP\Pays.txt" -Wait
IV. Récupérer les X premières lignes d'un
fichier
Dans le même esprit, on peut récupérer les premières lignes d'un fichier. Dans ce
cas, on ne va pas utiliser -Tail mais plutôt -TotalCount à la place. Là encore, il
faut spécifier le nombre de lignes à afficher.
Get-Content "C:\TEMP\Pays.txt" -TotalCount 5
Par contre, et c'est logique, l'option -Wait n'a pas d'utilité avec l'option -
TotalCount.
V. NTFS : consulter un stream secret
dans un fichier
Le système de fichiers NTFS a la particularité d'avoir différents "stream" dans
lequel stocker les données. Lorsque l'on écrit des données dans un fichier, elles
sont stockées dans le flux $DATA. Ainsi, lorsque l'on consulte le fichier, on va
lire le contenu de ce flux de données.
D'ailleurs, on peut voir que notre fichier "Pays.txt" dispose bien de ce stream
grâce à la commande Get-Item :
Get-Item "C:\TEMP\Pays.txt" -Stream *
On remarque également que la console retourne seulement ce flux de données.
Là où c'est cool, c'est que l'on peut créer son propre stream pour cacher des
données à l'intérieur ! ?
Il suffit d'ajouter des données à notre fichier "Pays.txt" en spécifiant
le stream dans lequel envoyer les données. Par exemple, nous allons créer le
stream "Creds" avec la valeur "MotDePasse".
Add-Content -Path "C:\TEMP\Pays.txt" -Stream Creds -Value "MotDePasse"
Maintenant, si on affiche à nouveau la liste des streams de notre fichier, on
obtient une nouvelle entrée :
Si l'on s'amuse à afficher le contenu de notre fichier, on verra que la valeur
"MotDePasse" que je viens d'ajouter au fichier ne ressort pas.
Get-Content "C:\TEMP\Pays.txt"
D'ailleurs, pour consulter le flux par défaut, on peut préciser son nom à la suite du
paramètre -Stream de Get-Content (attention à la syntaxe) :
Get-Content "C:\TEMP\Pays.txt" -Stream ':$DATA'
Si l'on veut afficher le contenu du stream "Creds" que l'on a créé précédemment,
il suffit de le dire :
Get-Content "C:\TEMP\Pays.txt" -Stream Creds
La commande va retourner une seule valeur : MotDePasse
La preuve en image ci-dessous :
C'est à connaître, mais il ne faut pas non plus se dire que c'est la solution miracle
pour cacher des mots de passe ou des données confidentielles. En fait, on peut
scanner le système avec des outils spécifiques ou Get-ChildItem à la recherche de
fichiers qui ont un stream supplémentaire que le $DATA par défaut.
C'est un peu hors sujet, mais pour effectuer cette analyse à partir d'un dossier
courant comme point de départ :
Get-ChildItem -Recurse | ForEach { Get-Item $_.FullName -Stream * } | Where
stream -ne ':$Data'
Cette commande fera ressortir notre fichier Pays.txt et son stream "Creds" ?. Il est
fort possible des documents Office soient également mis en avant par la sortie de
la commande avec un stream nommé "Zone.Identifier". Il contient un ID qui
permet au système de connaître la zone d'appartenance de ce fichier
(intranet, internet, etc.. vis-à-vis des zones IE).
Nous venons de voir, dans le détail, comment utiliser la commande Get-
Content de PowerShell.