Windows 10 : comment supprimer les anciens profils utilisateurs ?
Sommaire
I. Présentation
Sur les postes de travail, et dans une moindre en mesure sur les serveurs, bien que cela touche les serveurs RDS, il est important de réaliser un nettoyage régulier des profils utilisateurs inutilisés sur Windows. La conséquence : le dossier "C:\Users" des postes va devenir énorme, car il va accumuler les profils utilisateurs. Ceci est d'autant plus vrai lorsqu'il y a beaucoup de passage sur un même PC, notamment dans les établissements scolaires.
La solution appliquée ici fonctionne sur Windows 10 et Windows Server 2019, mais également sur les versions plus anciennes.
Tutoriel disponible au format vidéo :
II. Comment supprimer un profil manuellement dans Windows 10 ?
La mauvaise réponse, c'est de supprimer le dossier de l'utilisateur dans "C:\Users", car la suppression sera partielle. En effet, il y aura toujours des traces de ce profil dans le registre. Si c'est trop tard, et que vous avez déjà effectué cette action, la prochaine fois que l'utilisateur va se connecter sur le poste, il sera en profil temporaire. Pour rattraper le coup, vous devez accéder au registre (regedit.exe) et supprimer la clé correspondant à cet utilisateur à l'emplacement ci-dessous, comme je l'expliquais dans un ancien article (Supprimer correctement un profil utilisateur sur Windows).
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList
La bonne réponse pour supprimer manuellement un profil utilisateur, c'est la suivante.
Vous devez accéder au Panneau de configuration et cliquer sur "Système". Ensuite, sur la gauche, cliquez sur "Paramètres système avancés" : une fenêtre va s'ouvrir, elle s'intitule "Propriétés système".
Dans l'onglet "Paramètres système avancés", cliquez sur "Paramètres" dans la section "Profil des utilisateurs". Une autre fenêtre va s'ouvrir avec la liste de tous les profils utilisateurs stockés sur la machine.
Sélectionnez dans la liste celui que vous souhaitez supprimer, et cliquez sur le bouton "Supprimer". Validez.
Voilà, vous venez de supprimer proprement un compte utilisateur de votre PC !
III. Comment supprimer les profils plus anciens que X jours ?
Au niveau des stratégies de groupe, il y a un paramètre très intéressant qui permet de supprimer automatiquement les profils plus anciens que X jours : à partir du moment où le profil n'a pas était utilisé sur le poste en question. Une période comprise entre 30 et 90 jours me semble pertinente. Cette opération s'effectue au redémarrage du système donc si vous désirez l'utiliser sur un serveur, notamment pour nettoyer un serveur RDS, c'est une information à prendre en compte. Le serveur doit redémarrer pour effectuer le nettoyage.
Je vous invite à créer une GPO ou à modifier une GPO existante, et suivre le chemin suivant :
Configuration ordinateur > Stratégies > Modèles d'administration > Système > Profils utilisateur
Le fameux paramètre qui nous intéresse est le suivant :
Supprimer au redémarrage du système les profils utilisateur plus anciens qu'un nombre de jours spécifiés
Vous devez l'activer puis spécifier le nombre de jours que vous souhaitez. À chaque fois qu'un profil est réutilisé sur le poste, le compteur est remis à zéro pour ce profil.
IV. Nettoyer les profils utilisateurs avec PowerShell
PowerShell peut également nous aider à faire le nettoyage, en complément des deux méthodes précédentes. En fait, grâce à la WMI et à la classe "Win32_UserProfile" il est possible de récupérer des informations sur les profils. Il suffit d'essayer cette commande et de constater le résultat imbuvable qui est retourné :
Get-WMIObject -Class Win32_UserProfile
Néanmoins, il y a deux propriétés intéressantes pour ce que l'on cherche à faire :
- LocalPath : chemin vers le profil de l'utilisateur
- LastUseTime : date de la dernière utilisation du profil, au format timestamp
Afin de lister les profils des utilisateurs inutilisés depuis 30 jours au minimum, nous pouvons utiliser cette commande :
Get-WMIObject -Class Win32_UserProfile | Where {(!$_.Special) -and ($_.ConvertToDateTime($_.LastUseTime) -lt (Get-Date).AddDays(-30))} | ft LocalPath
Elle va retourner le chemin vers les profils concernés. Cette commande exclu les profils spéciaux (on va éviter de tout casser...). On peut également supprimer tous les profils concernés en ajoutant simplement Remove-WmiObject à la fin de la commande. En fait, je vous recommande d'ajouter -WhatIf pour "simuler" l'exécution de la commande et voir ce qu'elle va supprimer. L'idéal étant de tester avant d'exécuter cette commande en production !
Get-WMIObject -class Win32_UserProfile | Where {(!$_.Special) -and (!$_.Loaded) -and ($_.ConvertToDateTime($_.LastUseTime) -lt (Get-Date).AddDays(-30))} | Remove-WmiObject –WhatIf
Notamment les SID des utilisateurs dont les profils vont être supprimés :
WhatIf : Opération « Remove-WmiObject » en cours sur la cible « \\W10-CL1\root\cimv2:Win32_UserProfile.SID="S-1-5-21-2321128819-363875854-497869713-1123" ». WhatIf : Opération « Remove-WmiObject » en cours sur la cible « \\W10-CL1\root\cimv2:Win32_UserProfile.SID="S-1-5-21-2321128819-363875854-497869713-1115" ». WhatIf : Opération « Remove-WmiObject » en cours sur la cible « \\W10-CL1\root\cimv2:Win32_UserProfile.SID="S-1-5-21-2321128819-363875854-497869713-1112" ». WhatIf : Opération « Remove-WmiObject » en cours sur la cible « \\W10-CL1\root\cimv2:Win32_UserProfile.SID="S-1-5-21-2321128819-363875854-497869713-1103" ». WhatIf : Opération « Remove-WmiObject » en cours sur la cible « \\W10-CL1\root\cimv2:Win32_UserProfile.SID="S-1-5-21-2225225463-1972338755-285342862-1001" »
Il ne reste plus qu'à retirer -WhatIf et à faire le nettoyage sur votre machine de cette façon ou celle de votre choix ?
attention avec les 90 jours, si vous avez des femme enceinte dans vos structure
Bonjour,
Oui c’est une bonne remarque et j’aurais dû insister un peu plus là-dessus. Effectivement, en fonction de l’usage qui est fait d’un poste, il faut mettre une durée cohérente ou penser à agir en cas d’absence longue durée, ça évitera bien des soucis…
Cordialement,
Florian
Bonjour, j’ai un message d’erreur avec la commande powershell :
PS C:\Windows\system32> Get-WMIObject -Class Win32_UserProfile | Where {(!$_.Special) -and ($_.ConvertToDateTime($_.LastUseTime) -lt (Get-Date).AddDays(-30))} | ft LocalPath
Exception lors de l’appel de «ConvertToDateTime» avec «1» argument(s): «Exception lors de l’appel de «ToDateTime» avec «1» argument(s): «L’argument spécifié n’était pas dans les limites de la plage des valeurs valides.
Nom du paramètre : dmtfDate » »
Au caractère Ligne:1 : 49
+ … le | Where {(!$_.Special) -and ($_.ConvertToDateTime($_.LastUseTime) …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ScriptMethodRuntimeException
Merci pour cet article, je travaille en établissement scolaire et jadis j’utilisais Delprof mais cette solution m’a l’air désormais plus puissante. Continuez bien
Personnellement, je fixe une alerte à 90 jours, sans action automatique derrière.
Je flag ensuite le compte AD manuellement (après vérification auprès des RH) via un extendedAttribute pour suppression ultérieure (script exécuté automatiquement)
ça règle le problème comme ça 🙂
Peut-on mettre des exclusions de profils ?
Bonjour Fred,
A ma connaissance, ce n’est pas possible avec les paramètres de GPO disponibles. Par contre, en PowerShell c’est jouable 😉
Cordialement,
Florian
Merci Florian de me répondre.
En effet c’est powershell qui je travaille. Dans mon script j’ai plusieurs profils locaux qui ne doivent pas être supprimés. Quelle méthode d’exclusion me suggères-tu ?
Personnellement, je récupèrerai la liste des utilisateurs locaux existants via Get-LocalUser. En récupérant les proppriétés FullName & SID, on peut ensuite faire une comparaison avec un if avant suppression des profils.
Si le if matche, cela veut dire qu’il s’agit d’un profil à exclure, donc on ne fait rien pour ce profil là et on passe au suivant. ça pourrait ressembler à ça (à adapter bien sûr) :
$localuser = Get-LocalUser -Name Thibault
Foreach ($profile in $oldprofiles) {
if (($profile.Name -match $localuser.FullName) -or ($profile.SID -match $localuser.SID)) {
Write-Output »Profil exclus, on ne fait rien »
}
else {
Write-Output « On supprime »
}
}
Bonjour Florian,
merci pour cet article super interressant.
J’avais une petite question, comment faire, via powershell, pour ne supprimer que les comptes inconnus ?
Dès qu’on supprime un compte AD, le profil de se compte est considéré comme inconnu sur les serveurs. Via ta commande powershell, en la modifiant, il ne me sort que les comptes « connu ». Bizarre. Une idée ?
Tu dois sûrement voir le SID de ces comptes d’affiché. Comme les comptes ne sont plus connus par l’Active Directory, impossible de trouver une correspondance au niveau du nom.
Je vois 2 possibilités :
– Soit tu récupères le SID pour supprimer en commande PowerShell ce qu’il est nécessaire de supprimer
– Soit, lors de la suppression d’un compte AD, tu stockes le nom du compte + son SID pour usage ultérieur. Par exemple, tu peux générer un fichier .log en sortie de ton premier script de suppression des users, et dans ton second tu peux aller lire ce fichier pour récupérer les SID et finir les opérations.
Bonjour,
Que rajoutez si on souhaite executer cette commande a distance ? L’idée c’est de mettre nom de machines dans un .TXT et lancer le script.
Merci
L’utilisation de la commande ci-dessous:
Get-WMIObject -class Win32_UserProfile | Where {(!$_.Special) -and (!$_.Loaded) -and ($_.ConvertToDateTime($_.LastUseTime) -lt (Get-Date).AddDays(-30))}
Me remonte l’information suivante que je ne parviens pas à comprendre :
Exception lors de l’appel de « ConvertToDateTime » avec « 1 » argument(s) : « Exception lors de l’appel de « ToDateTime » avec « 1 » argument(s) : « L’argument spécifié n’était pas dans les limites de la plage des valeurs valides. Nom du paramètre : dmtfDate » »
Au caractère Ligne:1 : 49
+ … le | Where {(!$_.Special) -and (!$_.Loaded) -and ($_.ConvertToDateTim …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ScriptMethodRuntimeException
Merci de votre aide.
Cordialement
Bonjour,
j’ai le même problème? Est-ce la version de Powershell qui induit cela ?
Avez vous trouvé une solution ?
Bonjour,
Avant tout merci pour ce tuto, je débute en powershell, donc peut etre que mes questions paraitrons « bete » :
-j’ai besoin de supprimer des clés de registre d’un profil windows SANS supprimer le dossier dans c:\users (pour conserver d’éventuelles données) en filtrant sur le nom du profil
j’ai conçu ce script :
$sid = Get-WMIObject -Class Win32_UserProfile |where-object {$_.localpath -like « *nom_profile* »} |select SID
$sid = $sid -replace « @{SID= », » »
$sid = $sid -replace « } », » »
#set-location « hklm:\ »
$chemin = « HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\profilelist »
$list = get-childitem -path $chemin
foreach ($l in $list)
{
Convert-String $l
$ssid = -join (« $chemin », »\ », « $sid »)
if ($l -eq $ssid)
{
write-host « correspond »
}else{
write-host « ne correspond pas »
}}
mais le test de comparaison ne fonctionne pas car mes 2 variables sont de type différent, et la conversion donne cette erreur :
Convert-String : Impossible de trouver un paramètre positionnel acceptant l’argument «HKEY_LOCAL_MACHINE\Software\Microsoft\Windows
NT\CurrentVersion\profilelist\S-1-5-21-3839788556-2644482991-1667297231-1001».
Au caractère Ligne:11 : 2
+ Convert-String $l
+ ~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument : (:) [Convert-String], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.StringManipulation.ConvertStringCommand
-y a t il une différence pour supprimer un profil sur un poste selon si le profil est local ou itinérant ?
Merci pour ton aide.
$sid = (Get-CimInstance -ClassName Win32_UserProfile |where-object {$_.localpath -like ‘*nom_profile*’}).SID
$chemin = ‘HKLM:\Software\Microsoft\Windows NT\CurrentVersion\ProfileList’
$list = get-childitem -path $chemin
foreach ($l in $list){
$ssid = Split-Path $l.Name -Leaf
if ($ssid -eq $sid){
write-host ‘correspond’
}
else{
write-host ‘ne correspond pas’
}
}
Bonjour,
J’ai une solution office365. Les étudiants se connectent aux différents ordinateurs de l’école avec leur adresse mail et MDP (que je crée dans office 365).
J’aimerais supprimer les comptes des étudiants qui quittent l’école sur les ordinateurs (donc dans le c: users) en fin d’année.
Je suis obligé de passer pc par pc ou existe-il une solution dans la console admin d’office 365/Intune/Endpoint ?
Merci beaucoup pour votre retour
Bonjour,
Via les GPO, il y a un paramètre qui permet de supprimer automatiquement les profils non utilisés. J’en parle dans cet article : https://www.it-connect.fr/windows-10-comment-supprimer-les-anciens-profils-utilisateurs/
🙂
bonjour. Comment ajouter des exception dans la commande pour ne pas supprimer certains profils? par exemple les comptes admin locaux ont été supprimés. Seul l’admin du domain (celui en cours d’execution) à été conservé. merci
j’aimerais savoir si le gpo peut également supprimer les compte locaux, au quel cas ce sera un gros problème en cas de prooblème d’approbation