Home > Software engineering >  Correct way to access the USERPROFILE dir of a specific user in a script?
Correct way to access the USERPROFILE dir of a specific user in a script?

Time:08-28

I'm writing a script to perform some file operations in the USERPROFILE folder of each (local) user on a Windows machine.

I have found various examples that use $env:USERPROFILE to identify the profile directory of the current logged-in user. I have also seen examples that assume all user profiles are saved in C:\Users\ and iterate/filter over that folder.

However, profile folders can be moved on Windows. My aim is to find (robustly) the profile directory of a specific user, given either that user's username (string) or a LocalUser object.

I can get an array of User objects based on active accounts with-

$users = Get-LocalUser | Where-Object Enabled -eq true

But the properties of those LocalUser objects are limited, and the UserProfile path is not among them. I believe this information is stored in the registry. I've through the PowerShell docs multiple times, but I haven't yet found the correct incantation that will give me the path of a user profile for a given user, which I can use in a loop to iterate across all users and their profile folders.

CodePudding user response:

Perhaps something along this line:

$users = Get-LocalUser | Where-Object Enabled -eq true

$profilesRootDir = @(
 Get-ItemPropertyValue 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList' ProfilesDirectory)

ForEach ($User in $Users) {

  $UserPath = Join-Path -Path "$profilesRootDir" -ChildPath "$User"

  "User     : $User`n"  
  "User-Path: $UserPath" 
}

Output:

User     : Bruce
User-Path: C:\Users\Bruce

CodePudding user response:

You can retrieve the root (parent) directory of all user profile directories from the registry as follows:

$profilesRootDir = 
  Get-ItemPropertyValue 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList' ProfilesDirectory

To get a specific user's (say jdoe) profile directory, you can then use:

Join-Path $profilesRootDir jdoe

However, the ultimate source of truth is the ProfileImagePath value in the subkeys of the above registry key path, named for each user's SID (security identifier), which Get-LocalUser does provide (the output objects have a .SID property):

Thus, to reliably get the profile directories of all enabled local users, use the following:

Get-LocalUser | 
  Where-Object Enabled |
  ForEach-Object {
    # Note the use of ...\ProfileList\$($_.SID) and value name ProfileImagePath
    Get-ItemPropertyValue "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$($_.SID)" ProfileImagePath
  }
  • Related