<img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=1678611822423757&amp;ev=PageView&amp;noscript=1">
Defrag This

| Read. Reflect. Reboot.

How To Accurately Enumerate Windows User Profiles With PowerShell

Adam Bertram| August 10 2017

| IT insights

how-to-accurately-enumerate-windows-user-profiles-with-powershell.jpg

When trying to enumerate all profiles, you need a script that can account for a variety of scenarios.

An everyday task that many admins must perform when working with both Windows server and client operating systems is listing all user profiles. A user's profile is the usual place that every installed application, as well as Windows itself, places files and folders specific to a particular user. If an admin needs to remove, add or modify individual files for all users via a script, the usual reaction is to enumerate all of the folders in C:\Users. Since C:\Users is the folder location for most users, simply identifying each of these folders is sufficient. But what if we need to enumerate all profiles, including those owned by SYSTEM, Network Service and other operating system-specific profiles? Or, what happens if we're working with Windows XP, and the profiles are stored in C:\Documents and Settings instead? We need a script that can account for all of these scenarios.

To create a more robust script to enumerate user profiles, we can't simply list all of the folders in C:\Users. We need to query a location that will always point to all user profiles on a system, and for that, we need to head to the registry.

Read: Working With Windows Services In PowerShell

The registry contains a key called ProfileList located in HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion. This registry key contains one subkey for each user profile on a Windows machine. Inside of each of these subkeys is a registry value called ProfileImagePath that includes the profile path for all users.

Once we know this location, it is then a matter of figuring out how to get PowerShell to enumerate all of these values. Since PowerShell has a registry provider already built-in, we can use Get-ChildItem to enumerate all of these subkeys. You can see below that besides the standard system profiles, I just have a single Adam user on my system.

PS> Get-ChildItem 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion\ProfileList'


    Hive: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\ProfileList


Name                           Property
----                           --------
S-1-5-18                       Flags            : 12
                               ProfileImagePath : C:\Windows\system32\config\systemprofile
                               RefCount         : 1
                               Sid              : {1, 1, 0, 0...}
                               State            : 0
S-1-5-19                       ProfileImagePath : C:\Windows\ServiceProfiles\LocalService
                               Flags            : 0
                               State            : 0
S-1-5-20                       ProfileImagePath : C:\Windows\ServiceProfiles\NetworkService
                               Flags            : 0
                               State            : 0
S-1-5-21-3385963305-808838737- ProfileImagePath                        : C:\Users\defaultuser0
1911667508-1000                Flags                                   : 0
                               State                                   : 0
                               Sid                                     : {1, 5, 0, 0...}
                               ProfileAttemptedProfileDownloadTimeLow  : 0
                               ProfileAttemptedProfileDownloadTimeHigh : 0
                               ProfileLoadTimeLow                      : 0
                               ProfileLoadTimeHigh                     : 0
                               RefCount                                : 0
                               RunLogonScriptSync                      : 0
S-1-5-21-3385963305-808838737- ProfileImagePath                        : C:\Users\Adam
1911667508-1002                Flags                                   : 0
                               State                                   : 0
                               Sid                                     : {1, 5, 0, 0...}
                               ProfileAttemptedProfileDownloadTimeLow  : 0
                               ProfileAttemptedProfileDownloadTimeHigh : 0
                               ProfileLoadTimeLow                      : 0
                               ProfileLoadTimeHigh                     : 0
                               RefCount                                : 15
                               RunLogonScriptSync                      : 0

Being able to see these profiles is a start, but we will need to use the specific folder paths in our script somewhere. For that, we only have to see the values of ProfileImagePath for each user. To return the registry value for each of the user's subkeys, we will invoke the GetValue() method on each of the registry keys to just see the user profile path.

PS> Get-ChildItem 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion\ProfileList' | ForEach-Object { $_.GetValue('ProfileImagePath') }
C:\Windows\system32\config\systemprofile
C:\Windows\ServiceProfiles\LocalService
C:\Windows\ServiceProfiles\NetworkService
C:\Users\defaultuser0
C:\Users\Adam

By looping over each registry key with ForEach-Object and then calling the GetValue() method on each ProfileImagePath value, it will now return only the paths we're after. Once you've got the paths to each user profile, additional checks or codes can be performed on each folder. For example, each user's temp folder path is located in the AppData\Local\Temp folder. To enumerate every user's temp folder, you could add a command inside of your loop to list those files.

PowerShell PS> Get-ChildItem 'HKLM:\Software\Microsoft\Windows 
NT\CurrentVersion\ProfileList' | ForEach-Object {      $profilePath =
$_.GetValue('ProfileImagePath')     Get-ChildItem -Path
"$profilePath\AppData\Local\Temp" }

Once you've got a loop that includes every user profile path, you're open to doing anything you'd like to files or folders inside of each of those paths!

Topics: IT insights

Leave a Reply

Your email address will not be published. Required fields are marked *

THIS POST WAS WRITTEN BY Adam Bertram

Adam Bertram is a 20-year veteran of IT. He’s currently an automation engineer, blogger, independent consultant, freelance writer, author, and trainer. Adam focuses on DevOps, system management, and automation technologies as well as various cloud platforms. He is a Microsoft Cloud and Datacenter Management MVP and efficiency nerd that enjoys teaching others a better way to leverage automation.

Free Trials

Getting started has never been easier. Download a trial today.

Download Free Trials

Contact Us

Let us know how we can help you. Focus on what matters. 

Send us a note

Subscribe to our Blog

Let’s stay in touch! Register to receive our blog updates.