Windows Server 2016 : Windows Update bloqué par un magasin saturé (SoftwareDistribution/WinSxS) – diagnostic, solutions et script PowerShell

Windows Server 2016 peut cesser de télécharger/installer les mises à jour lorsque le magasin local (SoftwareDistribution et WinSxS) se sature. Ce guide explique les causes, propose une procédure pas‑à‑pas, un script PowerShell et des bonnes pratiques pour pérenniser le correctif.

Sommaire

Vue d’ensemble du problème

De nombreux administrateurs constatent que Windows Update reste bloqué (recherche infinie, téléchargement à 0 %/100 % ou erreurs de maintenance). Dans la majorité des cas, la racine est une saturation ou une incohérence du magasin de maintenance :

  • C:\Windows\SoftwareDistribution : cache de téléchargement, base de données WU (DataStore.edb), rapports, files.
  • C:\Windows\WinSxS : Component Store (composants CBS) qui grossit au fil des remplacements (CU, LCU, .NET, etc.).
  • Registre CBS : la ruche HKLM\COMPONENTS contient des index dérivés, dont DerivedData\VersionedIndex, parfois cité comme cause/symptôme lorsqu’il est incohérent ou démesuré.

Conséquence : manque d’espace disque, tâches de maintenance incapables de purger, services WU en échec, BITS bloqué, voire corruption de l’index CBS.

Pourquoi cela se produit

  • Espace disque insuffisant sur la partition système (C:), souvent aggravé par des dumps mémoire et journaux volumineux.
  • Cache WU obsolète (SoftwareDistribution/catroot2) empêchant la validation d’états “pending”.
  • Component Store non nettoyé (WinSxS) : remplacement cumulatif sans purge, tâche planifiée désactivée, packages en attente.
  • Transferts BITS coincés qui ne libèrent ni ne valident les téléchargements partiels.
  • Index CBS (ex. VersionedIndex) volumineux/corrompu, empêchant la maintenance.
  • Chaîne SSU/CU : absence d’une Servicing Stack Update préalable pouvant bloquer un LCU (fréquent sur 2016).
  • WSUS : politique mal configurée, catalogue non synchronisé ou serveur indisponible.

Plan d’action rapide (TL;DR)

  1. Libérer de l’espace (journaux/dumps obsolètes, extension de disque si nécessaire).
  2. Réinitialiser Windows Update : arrêter wuauserv/bits/cryptsvc, renommer SoftwareDistribution et catroot2, redémarrer les services.
  3. Nettoyer WinSxS avec DISM (AnalyzeComponentStore, StartComponentCleanup, optionnel ResetBase).
  4. Exécuter/activer la tâche planifiée StartComponentCleanup.
  5. Vider les transferts BITS bloqués.
  6. Relancer la détection (usoclient StartScan), vérifier WSUS/GPO.
  7. En dernier recours, installer manuellement une KB critique pour débloquer la séquence.
  8. Redémarrer pour libérer les verrous et reconstruire les index.

Guide détaillé pas à pas

1) Vérifier et libérer l’espace disque

Visez un minimum de 10–15 Go libres sur C:. Sur machines virtuelles, envisagez l’extension du disque système.

  • Lister les volumes et l’espace libre : Get-PSDrive -PSProvider FileSystem | Sort-Object Used -Descending | Format-Table Name,Root,Used,Free
  • Rechercher les gros répertoires (exemples à auditer) :
    • C:\Windows\SoftwareDistribution\Download
    • C:\Windows\Logs\CBS et C:\Windows\Logs\DISM
    • C:\Windows\Temp et %TEMP%
    • C:\Windows\MEMORY.DMP, C:\Windows\Minidump
    • C:\Windows\WinSxS (ne pas supprimer manuellement)
  • Supprimer en sécurité : journaux anciens, dump obsolètes, fichiers temporaires. Évitez C:\Windows\Installer ou WinSxS sans outil système.
  • Installer “Nettoyage de disque” (si GUI) via les fonctionnalités “Desktop Experience” pour disposer de l’option “Nettoyage de Windows Update”.

2) Réinitialiser Windows Update (cache et catalogues)

Exécuter en Invite de commandes ou PowerShell avec élévation :

net stop wuauserv
net stop bits
net stop cryptsvc
sc query trustedinstaller | findstr /I RUNNING && net stop trustedinstaller

ren %systemroot%\SoftwareDistribution SoftwareDistribution.old
ren %systemroot%\System32\catroot2 catroot2.old

net start cryptsvc
net start bits
net start wuauserv 

Sur Server Core, les mêmes commandes s’appliquent. Cette réinitialisation supprime les métadonnées locales et force une redétection.

3) Nettoyer le Component Store (WinSxS) avec DISM

Analyser puis nettoyer :

Dism /Online /Cleanup-Image /AnalyzeComponentStore
Dism /Online /Cleanup-Image /StartComponentCleanup

Option avancée (irréversible) : supprimer les remplacements devenus inutiles :

Dism /Online /Cleanup-Image /StartComponentCleanup /ResetBase

Si des opérations sont marquées “en attente” et bloquent le nettoyage, testez :

Dism /Online /Cleanup-Image /RevertPendingActions</code></pre>
<p>Après ces opérations, il est recommandé de <strong>redémarrer</strong> le serveur pour libérer des verrous éventuels.</p>

<h3>4) Activer et exécuter la tâche planifiée de purge</h3>
<p>La tâche <em>StartComponentCleanup</em> purge automatiquement les composants &gt;&nbsp;30&nbsp;jours. Vérifier puis exécuter&nbsp;:</p>
<pre><code>schtasks /Query /TN \Microsoft\Windows\Servicing\StartComponentCleanup
schtasks /Run   /TN \Microsoft\Windows\Servicing\StartComponentCleanup
</code></pre>

<h3>5) Vider les transferts BITS bloqués</h3>
<p>Des jobs BITS en échec maintiennent des fichiers partiels. En PowerShell&nbsp;:</p>
<pre><code>Get-BitsTransfer -AllUsers | Where-Object {$_.JobState -in 'Error','TransientError','Transferred'} | Remove-BitsTransfer -Confirm:$false
</code></pre>

<h3>6) Regénérer/Collecter les journaux Windows&nbsp;Update</h3>
<p>Sur 2016, <code>Get-WindowsUpdateLog</code> reconstruit le journal lisible depuis les ETW&nbsp;:</p>
<pre><code>Get-WindowsUpdateLog -LogPath "$env:USERPROFILE\Desktop\WindowsUpdate.log"
</code></pre>
<p>Consultez aussi le journal “<em>WindowsUpdateClient/Operational</em>” dans l’Observateur d’événements et <code>C:\Windows\Logs\CBS\CBS.log</code> pour la maintenance CBS.</p>

<h3>7) Réparer les fichiers système (si corruption)</h3>
<p>Exécuter SFC puis DISM <em>RestoreHealth</em>&nbsp;:</p>
<pre><code>sfc /scannow
Dism /Online /Cleanup-Image /RestoreHealth
</code></pre>
<p>Si l’accès à Internet est restreint (serveur WSUS “offline”), fournissez une source locale (ISO/chemin <em>SxS</em>)&nbsp;:</p>
<pre><code>Dism /Online /Cleanup-Image /RestoreHealth /Source:D:\sources\sxs /LimitAccess
</code></pre>

<h3>8) Relancer la détection/installation des mises à jour</h3>
<p>Sur 2016, <code>usoclient</code> pilote la détection&nbsp;:</p>
<pre><code>usoclient StartScan
usoclient StartDownload
usoclient StartInstall
</code></pre>
<p>Si WSUS est utilisé, vérifiez la GPO “<em>Specify intranet Microsoft update service location</em>” et l’état de santé du serveur WSUS (synchronisation, approbations, espace disque).</p>

<h3>9) Installer manuellement une KB critique (déblocage)</h3>
<p>Lorsque la chaîne est cassée, installer une KB clé (<em>SSU</em> récente ou <em>LCU</em>) peut relancer le pipeline&nbsp;:</p>
<pre><code>wusa.exe C:\MisesAJour\KBxxxxxxx.msu /quiet /norestart
</code></pre>
<p>Surveillez ensuite l’Observateur d’événements et relancez un <em>StartScan</em>.</p>

<h3>10) À propos de <code>HKLM\COMPONENTS\DerivedData\VersionedIndex</code> (avancé)</h3>
<p>Ce sous-ensemble de la ruche CBS est généré par le moteur de maintenance. En principe, <strong>aucune modification manuelle n’est nécessaire</strong>. Les actions ci‑dessous ne sont à envisager qu’en dernier recours, avec sauvegarde préalable et fenêtre de maintenance&nbsp;:</p>
<ol>
  <li><strong>Exporter la ruche CBS</strong>&nbsp;:
    <pre><code>mkdir C:\CBS-Backup
reg save HKLM\COMPONENTS C:\CBS-Backup\COMPONENTS.hiv

Essayer d’abord la voie “propre” : réinitialisation WU, StartComponentCleanup, ResetBase, RestoreHealth, RevertPendingActions, puis redémarrage.
Éviter la suppression directe de clés (VersionedIndex) : un effacement arbitraire peut briser la cohérence du magasin et rendre inopérant le service de maintenance. Si la ruche est manifestement corrompue, préférez la restauration depuis un instantané sauvegardé et/ou une réparation hors‑ligne.

Tableau récapitulatif (actions & commandes)

ObjectifActions proposéesDétails / commandes utiles
Vérifier l’espace disqueAuditer C: et volumes de données, nettoyer logs/dumps, envisager l’extension du disque.Get-PSDrive -PSProvider FileSystem, Explorateur, Gestionnaire de serveur.
Relancer Windows UpdateArrêter WU/BITS/CRYPTO, renommer SoftwareDistribution et catroot2, redémarrer.net stop wuauserv && net stop bits && net stop cryptsvc ren %systemroot%\SoftwareDistribution SoftwareDistribution.old ren %systemroot%\System32\catroot2 catroot2.old net start cryptsvc && net start bits && net start wuauserv
Nettoyer le composant storeAnalyser puis nettoyer WinSxS ; optionnel ResetBase (irréversible).Dism /Online /Cleanup-Image /AnalyzeComponentStore Dism /Online /Cleanup-Image /StartComponentCleanup Dism /Online /Cleanup-Image /StartComponentCleanup /ResetBase
Activer le nettoyage automatiqueVérifier/activer la tâche planifiée de purge et l’exécuter à la demande.schtasks /Run /TN \Microsoft\Windows\Servicing\StartComponentCleanup
Dépannage BITSSupprimer les jobs en échec qui bloquent la progression.Get-BitsTransfer -AllUsers | ? JobState -in 'Error','TransientError','Transferred' | Remove-BitsTransfer -Confirm:$false
Outil de résolution de problèmes WUVia Paramètres → Mise à jour & sécurité → Dépannage → Windows Update.Réinitialisation guidée des composants WU (autorisations, catalogues).
Télécharger manuellement des KBRécupérer la KB (.msu) et l’installer silencieusement.wusa.exe KBxxxxxxx.msu /quiet /norestart
Contrôler le registre (facultatif)Vérifier la ruche HKLM\COMPONENTS ; éviter toute suppression directe.reg save HKLM\COMPONENTS C:\CBS-Backup\COMPONENTS.hiv Sauvegarder avant manipulation.

Script PowerShell tout‑en‑un (sécurisé)

Exécuter en tant qu’administrateur. Le script journalise les étapes, réinitialise WU, nettoie WinSxS, purge BITS et relance la détection. Ajustez les chemins si nécessaire.

#region Paramètres & journalisation
$ErrorActionPreference = 'Stop'
$Log = "C:\Temp\WS2016-WU-Fix-$(Get-Date -Format yyyyMMdd-HHmmss).log"
New-Item -Path (Split-Path $Log) -ItemType Directory -Force | Out-Null
function Write-Log($m){ $ts = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'; "$ts`t$m" | Tee-Object -FilePath $Log -Append }

Write-Log "Démarrage du correctif Windows Update pour WS2016"

# Vérif espace

$sys = Get-Volume -FileSystemLabel -ErrorAction SilentlyContinue | Out-Null
$free = (Get-PSDrive -Name C).Free
Write-Log ("Espace libre sur C: {0:N2} Go" -f ($free/1GB))

#region Étape 1: Stop services
$services = 'wuauserv','bits','cryptsvc'
foreach($s in $services){
Write-Log "Arrêt du service $s"
Stop-Service -Name $s -ErrorAction SilentlyContinue -Force
}

# TrustedInstaller si en cours

if((Get-Service -Name trustedinstaller -ErrorAction SilentlyContinue).Status -eq 'Running'){
Write-Log "Arrêt de TrustedInstaller"
Stop-Service trustedinstaller -Force
}

#region Étape 2: Renommage caches
$sd = "$env:SystemRoot\SoftwareDistribution"
$cr = "$env:SystemRoot\System32\catroot2"
foreach($p in @($sd,$cr)){
if(Test-Path $p){
$dest = "$p.$((Get-Date).ToString('yyyyMMddHHmmss')).old"
Write-Log "Renommage: $p -> $dest"
Rename-Item -Path $p -NewName (Split-Path $dest -Leaf)
}
}

#region Étape 3: Start services
foreach($s in @('cryptsvc','bits','wuauserv')){
Write-Log "Démarrage du service $s"
Start-Service $s
}

#region Étape 4: Purge BITS
try{
$jobs = Get-BitsTransfer -AllUsers -ErrorAction SilentlyContinue
if($jobs){
Write-Log ("Suppression {0} job(s) BITS" -f $jobs.Count)
$jobs | Remove-BitsTransfer -Confirm:$false
} else {
Write-Log "Aucun job BITS actif"
}
}catch{ Write-Log "BITS indisponible ou aucune tâche: $($_.Exception.Message)" }

#region Étape 5: DISM - Analyze/Cleanup
Write-Log "DISM AnalyzeComponentStore"
Start-Process -FilePath dism.exe -ArgumentList "/Online","/Cleanup-Image","/AnalyzeComponentStore" -Wait -NoNewWindow -PassThru | Out-Null
Write-Log "DISM StartComponentCleanup"
Start-Process -FilePath dism.exe -ArgumentList "/Online","/Cleanup-Image","/StartComponentCleanup" -Wait -NoNewWindow -PassThru | Out-Null

#region Étape 6: Tâche planifiée Servicing
Write-Log "Exécution de la tâche StartComponentCleanup"
Start-Process -FilePath schtasks.exe -ArgumentList "/Run","/TN","\Microsoft\Windows\Servicing\StartComponentCleanup" -Wait -NoNewWindow -PassThru | Out-Null

#region Étape 7: Relancer la détection WU
Write-Log "Relance de la détection Windows Update"
Start-Process -FilePath usoclient.exe -ArgumentList "StartScan" -NoNewWindow -PassThru | Out-Null

Write-Log "Terminé. Un redémarrage peut être requis pour libérer les verrous et finaliser le nettoyage."
#end

Validation après correctif

  • Mesurer l’espace libéré : répétez l’audit (Get-PSDrive).
  • Analyser WinSxS : Dism /Online /Cleanup-Image /AnalyzeComponentStore doit indiquer un niveau “Recommended” plus faible.
  • Tester Windows Update : détection, téléchargement et installation d’une mise à jour de test (ex. .NET ou Defender platform si applicable).
  • Observer les journaux : erreurs récurrentes dans WindowsUpdateClient/Operational ou CBS.log doivent disparaître.

Bonnes pratiques de prévention

  • Capacité : réserver 20–25 % de marge sur C: (au moins 10–15 Go libres constants).
  • Purge automatique : s’assurer que StartComponentCleanup est activée et s’exécute régulièrement.
  • Maintenance planifiée : inclure DISM StartComponentCleanup dans les fenêtres de maintenance mensuelles.
  • Antivirus/EDR : exclure les chemins C:\Windows\SoftwareDistribution et C:\Windows\WinSxS des analyses lourdes pour réduire les verrous.
  • WSUS : surveiller la santé (synchronisations, approbations, nettoyage du contenu), vérifier l’URL d’intranet et la connectivité depuis les serveurs membres.
  • VM : privilégier des disques dynamiques dimensionnés avec un seuil d’alerte et activer la surveillance de capacité.

FAQ (situations fréquentes)

Le dossier WinSxS est “énorme”. Puis‑je le supprimer ?
Non. WinSxS contient des liens physiques et des versions de secours. Seul DISM ou la tâche planifiée doivent être utilisés pour le réduire.

“AnalyzeComponentStore” recommande un nettoyage mais rien ne bouge.
Vérifiez qu’aucune opération n’est en attente (RevertPendingActions), redémarrez, puis exécutez StartComponentCleanup.

Est‑ce utile d’enregistrer des DLL WU (regsvr32) comme sur d’anciennes versions ?
Rarement sur 2016. La réinitialisation des services et des catalogues suffit dans la plupart des cas.

Que faire si VersionedIndex est très volumineux ?
Sauvegardez la ruche (reg save), effectuez les nettoyages DISM, redémarrez. Évitez les suppressions directes ; préférez une approche de réparation CBS encadrée et, si besoin, une restauration depuis sauvegarde.

Les mises à jour restent à 0 % via WSUS.
Contrôlez l’espace du serveur WSUS, ses pools IIS, et assurez‑vous que la GPO pointe bien vers le bon FQDN. Purgez les transferts BITS côté client.

Checklist opérationnelle

  • ✅ Espace libre ≥ 10–15 Go sur C:
  • SoftwareDistribution & catroot2 régénérés
  • StartComponentCleanup exécutée (et activée)
  • ✅ BITS sans jobs en erreur
  • ✅ DISM RestoreHealth & SFC OK
  • ✅ Détection/installation WU validées
  • ✅ Redémarrage effectué et journaux propres

Notes spécifiques environnement

  • Serveur membre de domaine/WSUS : valider la stratégie “Specify intranet Microsoft update service location”.
  • Cluster/Hyper‑V : planifier la bascule de rôle et les redémarrages pour éviter les indisponibilités.
  • Core vs GUI : toutes les opérations sont faisables en ligne de commande ; pour le nettoyage “Windows Update” de l’outil GUI, installez “Desktop Experience”.

Conclusion

Sur Windows Server 2016, les blocages Windows Update liés à la saturation de SoftwareDistribution et/ou de WinSxS se résolvent de manière fiable en combinant : réinitialisation des caches, nettoyage DISM (idéalement automatisé via la tâche planifiée), purge BITS, redémarrage et, si nécessaire, installation manuelle d’une KB pivot. La clé HKLM\COMPONENTS\DerivedData\VersionedIndex n’exige pas d’actions directes dans un scénario normal ; traitez‑la comme un indicateur d’état CBS et privilégiez les méthodes de maintenance prises en charge. En prévention, maintenez une marge de capacité, surveillez WSUS et intégrez ces opérations à votre routine de patch management.

Sommaire