Planification de tâches sous Windows

Mise en place

Créer le script PowerShell de test

Créez le dossier C:\Temp s'il n'existe pas, puis créez le fichier C:\Temp\script.ps1 avec ce contenu:

# script.ps1
$date = Get-Date
"Script exécuté à $date" | Out-File C:\Temp\log.txt -Append

Tester le script manuellement

Ouvrez PowerShell et exécutez:

C:\Temp\script.ps1
Get-Content C:\Temp\log.txt

Vous devriez voir une ligne avec la date et l'heure d'exécution.

Explorer une tâche existante

Ouvrir le Planificateur de tâches

  1. Appuyez sur Windows + R, tapez taskschd.msc et appuyez sur Entrée
  2. Ou recherchez "Planificateur de tâches" dans le menu Démarrer

Explorer une tâche système

  1. Dans le volet de gauche, cliquez sur "Bibliothèque du Planificateur de tâches"
  2. Naviguez vers "Microsoft" > "Windows" > "Windows Defender"
  3. Sélectionnez la tâche "Windows Defender Scheduled Scan"
  4. En bas, examinez les onglets suivants:
    • Général : Utilisateur d'exécution, privilèges
    • Déclencheurs : Quand la tâche s'exécute
    • Actions : Ce que fait la tâche
    • Conditions : Conditions d'alimentation, réseau, etc.
    • Paramètres : Comportement en cas d'échec, durée maximale, etc.
    • Historique : Journal d'exécution (activez-le si désactivé)

Créer une tâche via le GUI

Créer un dossier pour vos tâches

  1. Dans le Planificateur de tâches, faites un clic droit sur "Bibliothèque du Planificateur de tâches"
  2. Sélectionnez "Nouveau dossier"
  3. Nommez-le "Demo" et cliquez sur "OK"

Créer votre première tâche planifiée

  1. Sélectionnez le dossier "Demo"
  2. Dans le volet de droite, cliquez sur "Créer une tâche..."

Onglet Général

  1. Nom : Mon Script
  2. Vérifiez que l'emplacement est bien "\Demo"
  3. Dans "Options de sécurité":
    • Utilisateur : Sélectionnez votre compte Administrateur
    • Cochez "N'exécuter que si l'utilisateur est connecté"
    • Cochez "Exécuter avec les privilèges les plus élevés"

Onglet Déclencheurs

  1. Cliquez sur "Nouveau..."
  2. "Lancer la tâche" : Sélectionnez "Une fois"
  3. Définissez la date et l'heure : 10 minutes à partir de maintenant
  4. Cliquez sur "OK"

Onglet Actions

  1. Cliquez sur "Nouveau..."
  2. Action : "Démarrer un programme"
  3. Programme/script : C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
  4. Ajouter des arguments : -File C:\Temp\script.ps1
  5. Cliquez sur "OK"

Onglet Conditions

  1. Décochez "Ne démarrer la tâche que si l'ordinateur est alimenté par le secteur"

Finaliser

  1. Cliquez sur "OK" pour créer la tâche

Vérifier la création

  1. Dans le dossier "Demo", vous devriez voir "Mon Script"
  2. En bas, l'onglet "Historique" devrait montrer un événement de création

Attendre l'exécution et vérifier

Attendez que l'heure programmée arrive (10 minutes), puis:

# Vérifier le fichier log
Get-Content C:\Temp\log.txt

# Voir la dernière ligne
Get-Content C:\Temp\log.txt | Select-Object -Last 1

Dans le Planificateur de tâches:

  1. Sélectionnez votre tâche "Mon Script"
  2. Cliquez sur l'onglet "Historique"
  3. Cherchez les événements ID 100 (démarré), 102 (terminé), 201 (succès)

Dépannage d'une tâche

Créer une tâche qui échoue volontairement

Créez une nouvelle tâche "Test Echec" qui pointe vers un script inexistant:

  • Programme : powershell.exe
  • Arguments : -File C:\Temp\script_inexistant.ps1
  • Déclencheur : Dans 2 minutes

Diagnostiquer l'échec

Après l'heure programmée:

  1. Dans le Planificateur:

    • Onglet "Historique" : Dans l'événement ID 201 (Action terminée), vous remarquerez un code de sortie non nul (indiquant un échec).
  2. Via PowerShell:

# Voir les événements récents du planificateur pour votre tâche
Get-WinEvent -LogName "Microsoft-Windows-TaskScheduler/Operational" | 
    Where-Object {$_.Message -like "*Test Echec*"} | 
    Select-Object TimeCreated, Id, Message |
    Format-List

Nettoyer

Supprimez la tâche "Test Echec" (clic droit > "Supprimer")

Background Jobs

Démarrer un job en arrière-plan

# Démarrer le job
Start-Job -Name "TestConnexion" -ScriptBlock {
    Test-Connection -ComputerName google.com -Count 100
} 

La commande Test-Connection envoie une série de requêtes ping avec un délai par défaut de 2 secondes entre chaque. Ainsi, avec le paramètre -Count 100, cette commande prendra environ 3 minutes et 20 secondes. Si vous exécutez cette commande dans une console PowerShell normale, vous devrez attendre qu'elle se termine avant de pouvoir utiliser à nouveau le terminal. En utilisant Start-Job, la commande s'exécute en arrière-plan. Ainsi, pendant l'exécution du job, votre terminal reste utilisable!

Vérifier l'état du job

# Voir tous les jobs
Get-Job

# Voir un job spécifique
Get-Job -Name "TestConnexion"

# Voir juste l'état
$job = Get-Job -Name "TestConnexion"
$job.State  # Running, Completed, Failed...

Attendre la fin du job

# Attendre avec timeout de 1 minute
Wait-Job -Name "TestConnexion" -Timeout 60

La commande Wait-Job bloque l'exécution jusqu'à ce que le job soit terminé ou que le délai soit écoulé. Cela peut être utile si vous voulez vous assurer que le job est terminé avant de récupérer les résultats.

Récupérer les résultats

Pour récupérer les résultats d'un job, utilisez Receive-Job. Par défaut, cela supprime les résultats du job après la récupération. Si vous voulez conserver le job pour une récupération ultérieure, utilisez l'option -Keep.

Si le job n'est pas encore terminé, Receive-Job récupérera les résultats disponibles jusqu'à présent. Si l'option -Keep n'est pas utilisé, les résultats obtenus seront supprimés après la récupération.

# Récupérer les résultats (supprime les résultats du job par défaut)
Receive-Job -Name "TestConnexion"

# OU récupérer sans supprimer
Receive-Job -Name "TestConnexion" -Keep

Vérifier avant de récupérer

Une bonne pratique est de vérifier l'état du job avant de tenter de récupérer les résultats. Cela permet d'éviter les erreurs si le job a échoué ou n'est pas encore terminé. Voici un exemple de script pour vérifier l'état avant de récupérer les résultats:

$job = Get-Job -Name "TestConnexion"

if ($job.State -eq "Completed") {
    $resultats = Receive-Job -Job $job -Keep
    Write-Host "Job terminé avec succès" -ForegroundColor Green
} elseif ($job.State -eq "Failed") {
    Write-Host "Job échoué. Erreur:" -ForegroundColor Red
    Receive-Job -Job $job -Keep
}

Nettoyer

# Supprimer le job
Remove-Job -Name "TestConnexion"

# Ou supprimer tous les jobs
Get-Job | Remove-Job

Scheduled Jobs (Jobs planifiés)

Nous allons maintenant créer un job planifié qui s'exécute automatiquement à des horaires définis.

Importer le module

Import-Module PSScheduledJob

Créer un job planifié quotidien

# Créer avec un déclencheur quotidien (changez l'heure pour dans 5 minutes)
Register-ScheduledJob -Name "MonJobPlanifie" `
    -FilePath C:\Temp\script.ps1 `
    -Trigger (New-JobTrigger -Daily -At "14:00")

Vérifier la création

# Voir les jobs planifiés
Get-ScheduledJob

# Voir les détails d'un job
Get-ScheduledJob -Name "MonJobPlanifie" | Format-List

Voir les déclencheurs

# Détails du déclencheur
Get-JobTrigger -Name "MonJobPlanifie"

Ajouter un déclencheur supplémentaire

# Ajouter un déclencheur hebdomadaire
$nouveauDeclencheur = New-JobTrigger -Weekly -DaysOfWeek Monday -At "10:00"
Add-JobTrigger -Name "MonJobPlanifie" -Trigger $nouveauDeclencheur

# Vérifier les deux déclencheurs
Get-JobTrigger -Name "MonJobPlanifie"

Configurer les options

Comme une tâche planifiée avec le GUI, vous pouvez configurer des options pour contrôler le comportement du job planifié. Nous allons ici modifier la politique de multi-instance pour ajouter les nouvelles exécutions dans une file d'attente (au lieu de les exécuter simultanément ou de les ignorer).

# Voir les options actuelles
Get-ScheduledJobOption -Name "MonJobPlanifie"

# Modifier la politique de multi-instance
Get-ScheduledJobOption -Name "MonJobPlanifie" | Set-ScheduledJobOption -MultipleInstancePolicy Queue

# Vérifier
Get-ScheduledJobOption -Name "MonJobPlanifie"

Démarrer manuellement

Nous allons maintenant démarrer manuellement le job plusieurs fois.

# Lancer maintenant (indépendamment de l'horaire)
Start-Job -DefinitionName "MonJobPlanifie"
Start-Job -DefinitionName "MonJobPlanifie"
Start-Job -DefinitionName "MonJobPlanifie"
Start-Job -DefinitionName "MonJobPlanifie"
...

Différence Get-ScheduledJob vs Get-Job

# UNE définition (le "modèle")
Get-ScheduledJob -Name "MonJobPlanifie"

# PLUSIEURS instances (les exécutions)
Get-Job -Name "MonJobPlanifie"

Récupérer les résultats

Comme pour les background jobs, utilisez Receive-Job pour récupérer les résultats des instances du job planifié. Chaque exécution du job planifié crée une instance distincte, et vous pouvez récupérer les résultats de chaque instance individuellement.

# Récupérer les résultats de toutes les instances
$jobInstances = Get-Job -Name "MonJobPlanifie"
foreach ($job in $jobInstances) {
    Write-Host "`nInstance ID $($job.Id):" -ForegroundColor Cyan
    Receive-Job -Job $job
}

Dans ce cas-ci, notre script script.ps1 écrit simplement dans un fichier log, et n'affiche pas de sortie (si tout se passe bien). Donc, vous ne verrez pas de résultats dans la console. Cependant, si le script avait une sortie (par exemple, des résultats de calcul ou des messages), ceux-ci seraient affichés ici.

Vérifier dans le Planificateur de tâches

  1. Ouvrez le Planificateur de tâches
  2. Naviguez vers : "Microsoft" > "Windows" > "PowerShell" > "ScheduledJobs"
  3. Vous devriez voir "MonJobPlanifie"
  4. Vous pouvez modifier via le GUI, mais c'est déconseillé (utilisez PowerShell)

Supprimer le job planifié

# Supprimer complètement
Unregister-ScheduledJob -Name "MonJobPlanifie"

# Vérifier
Get-ScheduledJob  # Ne devrait plus apparaître

Nettoyage final

Supprimer la tâche GUI

Dans le Planificateur de tâches :

  1. Sélectionnez votre tâche "Mon Script"
  2. Clic droit > "Supprimer"
  3. Confirmez

Supprimer les jobs planifiés

# Voir tous les jobs planifiés
Get-ScheduledJob

# Supprimer tous VOS jobs planifiés
Get-ScheduledJob | Unregister-ScheduledJob

# Supprimer les instances de jobs
Get-Job | Remove-Job

Nettoyer les fichiers de test

Remove-Item C:\Temp\log.txt -ErrorAction SilentlyContinue