Cours Complet PowerShell - Du Débutant à l'Expert
Table des Matières
1. Introduction à PowerShell
2. Installation et Configuration
3. Concepts Fondamentaux
4. Variables et Types de Données
5. Cmdlets Essentielles
6. Pipeline et Filtrage
7. Structures de Contrôle
8. Fonctions et Paramètres
9. Gestion des Erreurs
10. Manipulation de Fichiers
11. Administration Système
12. Scripts Avancés
13. Exemples Pratiques
1. Introduction à PowerShell {#introduction}
Qu'est-ce que PowerShell ?
PowerShell est un shell de ligne de commande et un langage de script orienté objet développé par
Microsoft. Contrairement aux shells traditionnels qui manipulent du texte, PowerShell travaille avec des
objets .NET.
Avantages de PowerShell
Orienté objet : Manipulation d'objets plutôt que de texte
Intégration .NET : Accès complet au framework .NET
Administration système : Gestion complète de Windows
Extensible : Modules et snap-ins
Cross-platform : Disponible sur Linux et macOS
2. Installation et Configuration {#installation}
Versions de PowerShell
Windows PowerShell : Version 5.1 (intégrée à Windows)
PowerShell Core : Version 7+ (multiplateforme)
Vérifier la version
powershell
$PSVersionTable
Politique d'exécution
powershell
# Vérifier la politique actuelle
Get-ExecutionPolicy
# Modifier la politique (en tant qu'administrateur)
Set-ExecutionPolicy RemoteSigned
3. Concepts Fondamentaux {#concepts}
Les Cmdlets
Les cmdlets suivent la syntaxe Verbe-Nom :
powershell
Get-Process
Set-Location
New-Item
Remove-File
Les Objets
Tout en PowerShell est un objet avec des propriétés et méthodes :
powershell
# Obtenir les propriétés d'un objet
Get-Process | Get-Member
# Accéder à une propriété
(Get-Process)[0].Name
L'aide intégrée
powershell
# Aide générale
Get-Help
# Aide pour une cmdlet spécifique
Get-Help Get-Process
# Aide détaillée avec exemples
Get-Help Get-Process -Examples
4. Variables et Types de Données {#variables}
Déclaration de variables
powershell
# Variables simples
$nom = "Jean Dupont"
$age = 30
$salaire = 2500.50
# Variables typées
[int]$nombre = 42
[string]$texte = "Hello World"
[datetime]$date = Get-Date
Types de données courants
powershell
# Chaînes de caractères
$message = "Bonjour $nom" # Interpolation
$literal = 'Texte littéral'
# Tableaux
$fruits = @("pomme", "banane", "orange")
$nombres = 1..10
# Tables de hachage
$personne = @{
Nom = "Dupont"
Prenom = "Jean"
Age = 30
}
# Booléens
$actif = $true
$termine = $false
Portée des variables
powershell
# Variable locale
$locale = "valeur"
# Variable globale
$global:globale = "valeur globale"
# Variable de script
$script:script = "valeur script"
5. Cmdlets Essentielles {#cmdlets}
Navigation et fichiers
powershell
# Navigation
Get-Location # pwd équivalent
Set-Location C:\ # cd équivalent
Get-ChildItem # ls équivalent
# Manipulation de fichiers
New-Item -Type File -Name "[Link]"
New-Item -Type Directory -Name "MonDossier"
Copy-Item "[Link]" "[Link]"
Move-Item "[Link]" "[Link]"
Remove-Item "[Link]"
Processus et services
powershell
# Processus
Get-Process
Get-Process -Name "notepad"
Stop-Process -Name "notepad"
# Services
Get-Service
Start-Service -Name "Spooler"
Stop-Service -Name "Spooler"
Informations système
powershell
# Informations système
Get-ComputerInfo
Get-WmiObject -Class Win32_OperatingSystem
Get-EventLog -LogName System -Newest 10
6. Pipeline et Filtrage {#pipeline}
Le Pipeline (|)
powershell
# Enchaîner des commandes
Get-Process | Sort-Object CPU -Descending | Select-Object -First 5
# Filtrer avec Where-Object
Get-Service | Where-Object {$_.Status -eq "Running"}
# Sélectionner des propriétés
Get-Process | Select-Object Name, CPU, WorkingSet
Alias courants
powershell
# Where-Object
Get-Service | ? {$_.Status -eq "Running"}
# ForEach-Object
Get-Process | % {$_.[Link]()}
# Select-Object
Get-Process | select Name, CPU
Exemples pratiques de pipeline
powershell
# Trouver les gros fichiers
Get-ChildItem -Recurse | Where-Object {$_.Length -gt 100MB} | Sort-Object Length -Descending
# Processus consommant le plus de mémoire
Get-Process | Sort-Object WorkingSet -Descending | Select-Object -First 10 Name, WorkingSet
7. Structures de Contrôle {#controle}
Conditions (if/else)
powershell
$age = 18
if ($age -ge 18) {
Write-Host "Majeur"
} elseif ($age -ge 16) {
Write-Host "Presque majeur"
} else {
Write-Host "Mineur"
}
# Opérateurs de comparaison
# -eq (égal), -ne (différent), -gt (supérieur), -lt (inférieur)
# -ge (sup. ou égal), -le (inf. ou égal), -like (pattern), -match (regex)
Switch
powershell
$jour = "Lundi"
switch ($jour) {
"Lundi" { "Début de semaine" }
"Vendredi" { "Fin de semaine" }
{$_ -in @("Samedi", "Dimanche")} { "Weekend" }
default { "Jour normal" }
}
Boucles
powershell
# Boucle for
for ($i = 1; $i -le 10; $i++) {
Write-Host "Nombre: $i"
}
# Boucle foreach
$fruits = @("pomme", "banane", "orange")
foreach ($fruit in $fruits) {
Write-Host "Fruit: $fruit"
}
# Boucle while
$compteur = 1
while ($compteur -le 5) {
Write-Host "Compteur: $compteur"
$compteur++
}
# Boucle do-while
do {
$reponse = Read-Host "Continuer ? (o/n)"
} while ($reponse -ne "n")
8. Fonctions et Paramètres {#fonctions}
Fonctions simples
powershell
function Saluer {
Write-Host "Bonjour!"
}
# Appel de la fonction
Saluer
Fonctions avec paramètres
powershell
function Saluer-Personne {
param(
[string]$Nom,
[int]$Age = 0
)
Write-Host "Bonjour $Nom, vous avez $Age ans"
}
# Appels
Saluer-Personne -Nom "Jean" -Age 30
Saluer-Personne "Marie" # Age par défaut = 0
Fonctions avancées
powershell
function Get-TailleFichier {
[CmdletBinding()]
param(
[Parameter(Mandatory=$true, ValueFromPipeline=$true)]
[string[]]$Path,
[ValidateSet("Bytes", "KB", "MB", "GB")]
[string]$Unite = "MB"
)
process {
foreach ($Chemin in $Path) {
if (Test-Path $Chemin) {
$taille = (Get-Item $Chemin).Length
switch ($Unite) {
"KB" { $taille = $taille / 1KB }
"MB" { $taille = $taille / 1MB }
"GB" { $taille = $taille / 1GB }
}
[PSCustomObject]@{
Fichier = $Chemin
Taille = [math]::Round($taille, 2)
Unite = $Unite
}
}
}
}
}
Valeurs de retour
powershell
function Calculer-Carre {
param([int]$Nombre)
return $Nombre * $Nombre
# ou simplement: $Nombre * $Nombre
}
$resultat = Calculer-Carre 5
9. Gestion des Erreurs {#erreurs}
Try-Catch-Finally
powershell
try {
$fichier = Get-Content "fichier_inexistant.txt" -ErrorAction Stop
Write-Host "Fichier lu avec succès"
}
catch [[Link]] {
Write-Host "Erreur: Fichier non trouvé"
}
catch {
Write-Host "Erreur générale: $($_.[Link])"
}
finally {
Write-Host "Nettoyage effectué"
}
Gestion des erreurs silencieuses
powershell
# Continuer malgré les erreurs
Get-Process "processus_inexistant" -ErrorAction SilentlyContinue
# Stocker les erreurs dans une variable
Get-Process "test" -ErrorAction SilentlyContinue -ErrorVariable erreurs
if ($erreurs) {
Write-Host "Erreurs détectées: $($[Link])"
}
Validation et tests
powershell
function Test-FichierExiste {
param([string]$Path)
if (-not (Test-Path $Path)) {
throw "Le fichier '$Path' n'existe pas"
}
return $true
}
10. Manipulation de Fichiers {#fichiers}
Lecture de fichiers
powershell
# Lire tout le contenu
$contenu = Get-Content "[Link]"
# Lire ligne par ligne
Get-Content "[Link]" | ForEach-Object {
Write-Host "Ligne: $_"
}
# Lire avec encodage spécifique
Get-Content "[Link]" -Encoding UTF8
Écriture de fichiers
powershell
# Écrire du contenu
"Nouveau contenu" | Out-File "[Link]"
# Ajouter du contenu
"Ligne supplémentaire" | Add-Content "[Link]"
# Écriture formatée
$processes = Get-Process | Select-Object Name, CPU
$processes | Export-Csv "[Link]" -NoTypeInformation
Manipulation CSV
powershell
# Importer un CSV
$donnees = Import-Csv "[Link]"
# Filtrer et exporter
$donnees | Where-Object {$_.Age -gt 30} | Export-Csv "[Link]" -NoTypeInformation
Manipulation XML
powershell
# Lire XML
[xml]$xml = Get-Content "[Link]"
$[Link] | Where-Object {$_.key -eq "debug"}
# Créer XML
$xml = New-Object [Link]
$root = $[Link]("configuration")
$[Link]($root)
11. Administration Système {#admin}
Gestion des utilisateurs
powershell
# Utilisateurs locaux
Get-LocalUser
New-LocalUser -Name "TestUser" -Password (ConvertTo-SecureString "MotDePasse123!" -AsPlainText -Force)
Remove-LocalUser -Name "TestUser"
# Groupes
Get-LocalGroup
Add-LocalGroupMember -Group "Administrators" -Member "TestUser"
Gestion du registre
powershell
# Lire une valeur du registre
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion" -Name ProductName
# Créer une clé
New-Item "HKCU:\SOFTWARE\MonApp"
# Définir une valeur
Set-ItemProperty "HKCU:\SOFTWARE\MonApp" -Name "Version" -Value "1.0"
Gestion des tâches planifiées
powershell
# Lister les tâches
Get-ScheduledTask
# Créer une nouvelle tâche
$action = New-ScheduledTaskAction -Execute "[Link]"
$trigger = New-ScheduledTaskTrigger -Daily -At 9am
Register-ScheduledTask -TaskName "OuvrirNotepad" -Action $action -Trigger $trigger
Surveillance système
powershell
# Utilisation disque
Get-WmiObject -Class Win32_LogicalDisk | Select-Object DeviceID,
@{Name="Size(GB)";Expression={[math]::Round($_.Size/1GB,2)}},
@{Name="FreeSpace(GB)";Expression={[math]::Round($_.FreeSpace/1GB,2)}}
# Utilisation mémoire
Get-Counter "\Memory\Available MBytes"
# Processus par consommation CPU
Get-Process | Sort-Object CPU -Descending | Select-Object -First 10 Name, CPU, WorkingSet
12. Scripts Avancés {#avances}
Modules et import
powershell
# Importer un module
Import-Module ActiveDirectory
# Lister les modules disponibles
Get-Module -ListAvailable
# Créer un module simple (fichier .psm1)
function Get-MaFonction {
"Fonction de mon module"
}
Export-ModuleMember -Function Get-MaFonction
Script avec paramètres
powershell
# En-tête du script (.ps1)
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string]$NomServeur,
[int]$Port = 80,
[switch]$Verbose
)
if ($Verbose) {
Write-Host "Connexion au serveur $NomServeur sur le port $Port"
}
Programmation orientée objet
powershell
# Définir une classe
class Personne {
[string]$Nom
[int]$Age
Personne([string]$nom, [int]$age) {
$[Link] = $nom
$[Link] = $age
}
[string]Saluer() {
return "Bonjour, je suis $($[Link])"
}
}
# Utiliser la classe
$p = [Personne]::new("Jean", 30)
$[Link]()
Travail avec les APIs REST
powershell
# Appel GET simple
$response = Invoke-RestMethod -Uri "[Link]
# Appel POST avec données
$body = @{
name = "Test"
description = "Description test"
} | ConvertTo-Json
$response = Invoke-RestMethod -Uri "[Link] -Method POST -Body $body -ContentType "app
13. Exemples Pratiques {#exemples}
Script de sauvegarde
powershell
function Backup-Files {
param(
[string]$SourcePath,
[string]$BackupPath,
[int]$RetainDays = 30
)
$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
$backupFolder = Join-Path $BackupPath "Backup_$timestamp"
try {
# Créer le dossier de sauvegarde
New-Item -Path $backupFolder -ItemType Directory -Force
# Copier les fichiers
Copy-Item -Path "$SourcePath\*" -Destination $backupFolder -Recurse -Force
Write-Host "Sauvegarde créée: $backupFolder"
# Nettoyer les anciennes sauvegardes
$oldBackups = Get-ChildItem $BackupPath | Where-Object {
$_.Name -match "Backup_\d{8}_\d{6}" -and
$_.CreationTime -lt (Get-Date).AddDays(-$RetainDays)
}
$oldBackups | Remove-Item -Recurse -Force
Write-Host "Supprimé $($[Link]) ancienne(s) sauvegarde(s)"
} catch {
Write-Error "Erreur lors de la sauvegarde: $($_.[Link])"
}
}
# Utilisation
Backup-Files -SourcePath "C:\Documents" -BackupPath "D:\Backups" -RetainDays 7
Monitoring de services
powershell
function Monitor-Services {
param(
[string[]]$ServiceNames,
[string]$LogPath = "C:\Logs\[Link]"
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
foreach ($serviceName in $ServiceNames) {
try {
$service = Get-Service -Name $serviceName -ErrorAction Stop
if ($[Link] -ne "Running") {
$message = "[$timestamp] ALERTE: Le service '$serviceName' n'est pas en cours d'exécution (Status: $($servic
Write-Warning $message
$message | Add-Content -Path $LogPath
# Tentative de redémarrage
try {
Start-Service -Name $serviceName
$message = "[$timestamp] INFO: Service '$serviceName' redémarré avec succès"
Write-Host $message -ForegroundColor Green
$message | Add-Content -Path $LogPath
} catch {
$message = "[$timestamp] ERREUR: Impossible de redémarrer le service '$serviceName': $($_.[Link]
Write-Error $message
$message | Add-Content -Path $LogPath
}
} else {
$message = "[$timestamp] OK: Service '$serviceName' fonctionne correctement"
Write-Host $message -ForegroundColor Green
}
} catch {
$message = "[$timestamp] ERREUR: Service '$serviceName' introuvable: $($_.[Link])"
Write-Error $message
$message | Add-Content -Path $LogPath
}
}
}
# Utilisation
$services = @("Spooler", "BITS", "Themes")
Monitor-Services -ServiceNames $services
Nettoyage automatique
powershell
function Clean-TempFiles {
param(
[int]$DaysOld = 7,
[switch]$WhatIf
)
$tempPaths = @(
$env:TEMP,
"C:\Windows\Temp",
"$env:USERPROFILE\AppData\Local\Temp"
)
$totalSize = 0
$totalFiles = 0
foreach ($path in $tempPaths) {
if (Test-Path $path) {
Write-Host "Analyse du dossier: $path" -ForegroundColor Yellow
$oldFiles = Get-ChildItem -Path $path -Recurse -File |
Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-$DaysOld) }
foreach ($file in $oldFiles) {
try {
$totalSize += $[Link]
$totalFiles++
if ($WhatIf) {
Write-Host " [SIMULATION] Suppression: $($[Link])" -ForegroundColor Cyan
} else {
Remove-Item $[Link] -Force
Write-Host " Supprimé: $($[Link])" -ForegroundColor Green
}
} catch {
Write-Warning " Impossible de supprimer: $($[Link]) - $($_.[Link])"
}
}
}
}
$sizeMB = [math]::Round($totalSize / 1MB, 2)
$action = if ($WhatIf) { "seraient supprimés" } else { "supprimés" }
Write-Host "`nRésumé: $totalFiles fichier(s) $action, libérant $sizeMB MB" -ForegroundColor Magenta
}
# Utilisation
Clean-TempFiles -DaysOld 30 -WhatIf # Simulation
Clean-TempFiles -DaysOld 30 # Exécution réelle
Rapport système automatisé
powershell
function Generate-SystemReport {
param(
[string]$OutputPath = "C:\Reports\SystemReport_$(Get-Date -Format 'yyyyMMdd').html"
)
# Créer le dossier si nécessaire
$reportDir = Split-Path $OutputPath -Parent
if (-not (Test-Path $reportDir)) {
New-Item -Path $reportDir -ItemType Directory -Force
}
# Collecter les informations
$computerInfo = Get-ComputerInfo
$diskInfo = Get-WmiObject -Class Win32_LogicalDisk
$processes = Get-Process | Sort-Object WorkingSet -Descending | Select-Object -First 10
$services = Get-Service | Group-Object Status
# Générer le HTML
$html = @"
<!DOCTYPE html>
<html>
<head>
<title>Rapport Système - $(Get-Date -Format 'dd/MM/yyyy HH:mm')</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
h1, h2 { color: #2E86AB; }
table { border-collapse: collapse; width: 100%; margin: 10px 0; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
.running { color: green; }
.stopped { color: red; }
</style>
</head>
<body>
<h1>Rapport Système</h1>
<p><strong>Date de génération:</strong> $(Get-Date -Format 'dd/MM/yyyy HH:mm:ss')</p>
<p><strong>Ordinateur:</strong> $($[Link])</p>
<p><strong>Système:</strong> $($[Link])</p>
<h2>Utilisation des disques</h2>
<table>
<tr><th>Lecteur</th><th>Taille totale (GB)</th><th>Espace libre (GB)</th><th>% Utilisé</th></tr>
"@
foreach ($disk in $diskInfo) {
if ($[Link]) {
$sizeGB = [math]::Round($[Link] / 1GB, 2)
$freeGB = [math]::Round($[Link] / 1GB, 2)
$usedPercent = [math]::Round(($[Link] - $[Link]) / $[Link] * 100, 1)
$html += "<tr><td>$($[Link])</td><td>$sizeGB</td><td>$freeGB</td><td>$usedPercent%</td></
}
}
$html += @"
</table>
<h2>Top 10 Processus (Mémoire)</h2>
<table>
<tr><th>Nom</th><th>Mémoire (MB)</th><th>CPU</th></tr>
"@
foreach ($process in $processes) {
$memoryMB = [math]::Round($[Link] / 1MB, 2)
$html += "<tr><td>$($[Link])</td><td>$memoryMB</td><td>$($[Link])</td></tr>"
}
$html += @"
</table>
<h2>État des Services</h2>
<table>
<tr><th>État</th><th>Nombre</th></tr>
"@
foreach ($group in $services) {
$class = if ($[Link] -eq "Running") { "running" } else { "stopped" }
$html += "<tr><td class='$class'>$($[Link])</td><td>$($[Link])</td></tr>"
}
$html += @"
</table>
</body>
</html>
"@
# Sauvegarder le rapport
$html | Out-File -FilePath $OutputPath -Encoding UTF8
Write-Host "Rapport généré: $OutputPath" -ForegroundColor Green
# Ouvrir le rapport
Start-Process $OutputPath
}
# Utilisation
Generate-SystemReport
Conseils et Bonnes Pratiques
1. Conventions de nommage
Fonctions: Verbe-Nom (Get-UserInfo, Set-Configuration)
Variables: Casse Pascal ou camelCase ($UserName, $configPath)
Paramètres: Casse Pascal avec types explicites
2. Documentation
powershell
<#
.SYNOPSIS
Brève description de la fonction
.DESCRIPTION
Description détaillée
.PARAMETER NomParametre
Description du paramètre
.EXAMPLE
Get-UserInfo -UserName "jdupont"
Exemple d'utilisation
#>
3. Performance
Utilisez Where-Object avec des scriptblocks pour de meilleures performances
Préférez les cmdlets natifs aux boucles manuelles
Utilisez Measure-Command pour mesurer les performances
4. Sécurité
Validez toujours les entrées utilisateur
Utilisez ConvertTo-SecureString pour les mots de passe
Évitez d'exposer des informations sensibles dans les logs
5. Debugging
powershell
# Points d'arrêt
Set-PSBreakpoint -Script "monscript.ps1" -Line 25
# Variables de debug
$DebugPreference = "Continue"
Write-Debug "Information de debug"
# Trace des commandes
Set-PSDebug -Trace 1
Ressources Supplémentaires
Documentation officielle: Microsoft PowerShell Docs
PowerShell Gallery: Modules communautaires
ISE et VSCode: Environnements de développement recommandés
Tests: Framework Pester pour les tests unitaires
Ce cours couvre les aspects essentiels de PowerShell. Pratiquez régulièrement et n'hésitez pas à explorer les
modules spécialisés selon vos besoins (Active Directory, Exchange, Azure, etc.).