When trying to list 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 listall 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 list 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!
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.
Let our experts teach you how to use Sitefinity's best-in-class features to deliver compelling digital experiences.
Learn MoreSubscribe to get all the news, info and tutorials you need to build better business apps and sites
Progress collects the Personal Information set out in our Privacy Policy and the Supplemental Privacy notice for residents of California and other US States and uses it for the purposes stated in that policy.
You can also ask us not to share your Personal Information to third parties here: Do Not Sell or Share My Info
We see that you have already chosen to receive marketing materials from us. If you wish to change this at any time you may do so by clicking here.
Thank you for your continued interest in Progress. Based on either your previous activity on our websites or our ongoing relationship, we will keep you updated on our products, solutions, services, company news and events. If you decide that you want to be removed from our mailing lists at any time, you can change your contact preferences by clicking here.