Windows LAPS – Forcer le traitement de la politique et analyser les événements avec PowerShell
Windows LAPS (Local Administrator Password Solution) est devenu un composant natif de Windows depuis la mise à jour d'avril 2023. Il remplace avantageusement l'ancienne solution LAPS en intégrant nativement la rotation des mots de passe des comptes administrateurs locaux — que ce soit via Active Directory, Azure AD / Entra ID ou en mode Workgroup.
Dans un contexte de gestion à distance via Azure Run Command, j'ai eu besoin de forcer manuellement le traitement de la politique LAPS et d'en analyser le résultat de manière fiable, sans aucune interaction utilisateur. Voici le script que j'ai mis en place.
🔍 Contexte et problématique
Le cmdlet Invoke-LapsPolicyProcessing ne retourne aucune sortie structurée.
La seule source d'information fiable reste le journal d'événements Windows LAPS :
Applications and Services Logs → Microsoft → Windows → LAPS → Operational
| Event ID | Signification |
|---|---|
| 10003 | Début du cycle de traitement |
| 10004 | ✅ Traitement terminé avec succès |
| 10005 | ❌ Traitement en échec (avec code d'erreur) |
☁️ Contraintes Azure Run Command
Plusieurs fonctionnalités PowerShell sont incompatibles avec l'exécution distante et ont été supprimées :
- ❌
$Host.UI.RawUI.ReadKey()— bloque indéfiniment l'exécution - ❌
Write-Progress— non capturé dans la sortie distante - ❌
Write-Host— remplacé parWrite-Output - ❌
Format-Table/Format-List— rendu instable en remote
📄 Script complet
#Requires -RunAsAdministrator
<#
.SYNOPSIS
PowerShell script to run Invoke-LapsPolicyProcessing, wait 10 seconds,
then retrieve and analyze Windows LAPS events to obtain the result (success/failure) and the last error.
.DESCRIPTION
The Invoke-LapsPolicyProcessing cmdlet does not return detailed information.
This script forces LAPS policy processing, waits for events to be written,
then queries the Microsoft-Windows-LAPS/Operational event log
to display the result of the processing cycle (Event ID 10003 to 10004 or 10005)
and the last detected error.
.NOTES
Author : Generated for user
Date : June 2026
Requires: Windows with Windows LAPS installed (LAPS module available)
Run as : Administrator (required)
Context : Azure Run Command (no interactive prompt)
#>
Write-Output "============================================================"
Write-Output " SCRIPT: Invoke-LapsPolicyProcessing + Wait + LAPS Log Analysis"
Write-Output "============================================================"
Write-Output ""
# ── Check if the LAPS PowerShell module is available ─────────────────────────
$lapsModule = Get-Module -ListAvailable -Name LAPS -ErrorAction SilentlyContinue
if (-not $lapsModule) {
Write-Warning "The PowerShell module 'LAPS' was not detected."
Write-Warning "Please ensure Windows LAPS is installed on this system."
Write-Warning "(Windows 11 22H2+, Windows Server 2022/2025 with the appropriate update)"
}
Write-Output "Running Invoke-LapsPolicyProcessing..."
$beforeProcessing = Get-Date
# ── Invoke LAPS policy processing ────────────────────────────────────────────
try {
# Run the cmdlet (usually returns nothing on success)
Invoke-LapsPolicyProcessing -ErrorAction Stop
Write-Output "SUCCESS: Cmdlet executed without PowerShell error."
} catch {
Write-Error "ERROR while running Invoke-LapsPolicyProcessing: $_"
exit 1
}
Write-Output ""
Write-Output "Waiting 10 seconds to allow events to be written to the LAPS event log..."
# ── Simple wait — no interactive progress bar (Azure remote compatible) ───────
Start-Sleep -Seconds 10
Write-Output "Wait complete."
Write-Output ""
# =============================================================================
# LAPS EVENT LOG QUERY
# =============================================================================
$logName = 'Microsoft-Windows-LAPS/Operational'
Write-Output "Searching for LAPS events generated by this processing cycle..."
Write-Output "Log: $logName"
Write-Output ""
# ── Main event log query block ────────────────────────────────────────────────
try {
# Retrieve events from just before the cmdlet was called (with a small buffer)
$events = Get-WinEvent -LogName $logName -MaxEvents 50 -ErrorAction Stop |
Where-Object { $_.TimeCreated -ge $beforeProcessing.AddSeconds(-5) }
if ($events.Count -eq 0) {
# No recent events found — explain possible reasons
Write-Warning "No recent LAPS events found since the processing was triggered."
Write-Warning "This may occur if:"
Write-Warning " - Processing made no changes (policy already applied)"
Write-Warning " - The log is empty or events were written too quickly"
Write-Warning " - You do not have read access to the event log"
} else {
Write-Output "LAPS events detected for this processing cycle:"
Write-Output ""
# ── Display a formatted summary of detected events ────────────────────
foreach ($evt in $events) {
$excerpt = ($evt.Message -replace "`r`n|`n", " " -replace "\s+", " ").Trim()
$excerpt = $excerpt.Substring(0, [Math]::Min(120, $excerpt.Length))
Write-Output " [$($evt.TimeCreated.ToString('HH:mm:ss'))] ID=$($evt.Id) | Level=$($evt.LevelDisplayName) | $excerpt"
}
Write-Output ""
# ── Determine the processing outcome — Event 10004 = Success, 10005 = Failure
$endEvent = $events | Where-Object { $_.Id -in @(10004, 10005) } | Select-Object -First 1
if ($endEvent) {
if ($endEvent.Id -eq 10004) {
# Processing completed successfully
Write-Output "============================================================"
Write-Output " RESULT: SUCCESS (Event ID 10004)"
Write-Output " LAPS policy processing succeeded."
Write-Output "============================================================"
} elseif ($endEvent.Id -eq 10005) {
# Processing failed — display full error message
Write-Output "============================================================"
Write-Output " RESULT: FAILURE (Event ID 10005)"
Write-Output " LAPS policy processing failed."
Write-Output "============================================================"
Write-Output ""
Write-Output "Error details:"
Write-Output $endEvent.Message
}
} else {
# No clear end-of-cycle event found — show the most recent event instead
Write-Warning "No end-of-cycle event (10004/10005) detected within this time window."
Write-Warning "Displaying the most recent LAPS event:"
$lastEvent = $events | Select-Object -First 1
Write-Output " Time : $($lastEvent.TimeCreated)"
Write-Output " Event ID: $($lastEvent.Id)"
Write-Output " Level : $($lastEvent.LevelDisplayName)"
Write-Output " Message : $($lastEvent.Message)"
}
# ── Search for the last error or warning event in this cycle ──────────
$lastError = $events | Where-Object {
$_.LevelDisplayName -eq 'Error' -or
$_.Id -eq 10005 -or
$_.Message -match 'failed|error'
} | Select-Object -First 1
if ($lastError -and $lastError.Id -ne 10004) {
Write-Output ""
Write-Output "============================================================"
Write-Output " LAST ERROR / WARNING EVENT DETECTED:"
Write-Output "============================================================"
Write-Output " Time : $($lastError.TimeCreated)"
Write-Output " Event ID : $($lastError.Id)"
Write-Output " Level : $($lastError.LevelDisplayName)"
Write-Output ""
Write-Output " Message:"
Write-Output " $($lastError.Message)"
Write-Output "============================================================"
}
}
} catch [System.Exception] {
# ── Handle event log read errors ──────────────────────────────────────────
if ($_.Exception.Message -like "*No events were found*") {
Write-Warning "The Microsoft-Windows-LAPS/Operational log exists but contains no recent events."
} else {
Write-Error "Error while reading the event log: $($_.Exception.Message)"
Write-Warning "Verify that the log exists in Event Viewer:"
Write-Warning " Applications and Services Logs > Microsoft > Windows > LAPS > Operational"
}
}
# =============================================================================
# TIPS AND USEFUL COMMANDS
# =============================================================================
Write-Output ""
Write-Output "============================================================"
Write-Output "TIPS:"
Write-Output " - Full diagnostic report:"
Write-Output " Get-LapsDiagnostics -OutputFolder 'C:\Temp\LAPS-Diag'"
Write-Output ""
Write-Output " - View all events manually:"
Write-Output " Get-WinEvent -LogName 'Microsoft-Windows-LAPS/Operational' -MaxEvents 20 | Format-List"
Write-Output ""
Write-Output " Key Event IDs:"
Write-Output " 10003 = Processing started"
Write-Output " 10004 = Processing succeeded"
Write-Output " 10005 = Processing failed (includes error code)"
Write-Output "============================================================"
Write-Output ""
Write-Output "Script completed."
⚠️ Points d'attention
- Le script requiert les droits Administrateur — la directive
#Requires -RunAsAdministratorest présente en en-tête. - Si aucun événement récent n'est détecté, la politique était peut-être déjà appliquée — ce n'est pas nécessairement une erreur.
- Le journal
Microsoft-Windows-LAPS/Operationaldoit exister sur la machine cible. - Pour un diagnostic complet :
Get-LapsDiagnostics -OutputFolder "C:\Temp\LAPS-Diag"
✅ Conclusion
Windows LAPS manque de verbosité native, mais l'analyse des Event IDs 10004 et 10005 permet d'obtenir un résultat fiable, même via Azure Run Command sans aucune interaction utilisateur. Ce script est directement réutilisable dans vos runbooks Azure Automation ou vos remediations Intune.
💬 Des questions ou retours d'expérience sur Windows LAPS ou Azure Run Command ? Les commentaires sont ouverts.
Commentaires
Enregistrer un commentaire