Windows 10 : comment supprimer les anciens profils utilisateurs ?

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 ?

Partagez cet article Partager sur Twitter Partager sur Facebook Partager sur Linkedin Partager sur Google+ Envoyer par mail

Florian Burnel

Ingénieur système et réseau, cofondateur d'IT-Connect et Microsoft MVP "Cloud and Datacenter Management". Je souhaite partager mon expérience et mes découvertes au travers de mes articles. Généraliste avec une attirance particulière pour les solutions Microsoft et le scripting. Bonne lecture.

florian has 3381 posts and counting.See all posts by florian

14 thoughts on “Windows 10 : comment supprimer les anciens profils utilisateurs ?

  • attention avec les 90 jours, si vous avez des femme enceinte dans vos structure

    Répondre
    • 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

      Répondre
    • 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

      Répondre
    • 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 🙂

      Répondre
    • 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

      Répondre
      • 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 ?

        Répondre
        • 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 »
          }
          }

          Répondre
  • 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 ?

    Répondre
    • 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.

      Répondre
  • 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

    Répondre
  • 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

    Répondre
  • 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.

    Répondre
    • $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’
      }
      }

      Répondre

Répondre à leblanc Annuler la réponse

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

 

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.