I am working on a script to install Epicor.exe through PowerShell. I am using $desktopPath = "$($env:userprofile)\Desktop" for part of this script but instead of going to the logged on user's desktop it is going to the user desktop of the person running the script. I.E. If an admin runs this, it will go to the admins desktop.
$env:username will take the username of whatever account is running the script, it will not get the logged in user.
UserProfile Management with PowerShell
powershell - Correct way to access the USERPROFILE dir of a specific user in a script? - Stack Overflow
Get userprofile path for current logged in user.
${Env:USERPROFILE} in administrator shell
Videos
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 profile directory, say jdoe, you can then use:
# See more robust alternative below.
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, it is better to use:
Get-ItemPropertyValue "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$((Get-LocalUser jdoe).SID)" ProfileImagePath
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
}
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
Hello Powershellers
In my current environment, there are several users who’s profile folder name is different than their username due to AD changes. So I’m looking for a way to find the profile path of the logged in user and I can’t necessarily rely on the username. The other twist is that the power shell script is run by third party software and I’m not sure which service it runs as because $env:Userprofile variable doesn’t work when using the software. Any other ideas on how I can do this? My end goal is to copy a shortcut that is under a users profile to the startup folder.
Windows can create a user-profile on-demand, using the CreateProfile API
However, if don't want to create an executable to perform this operation, you can call the API in PowerShell. Others have already done it: example on github.
Relevant part of the code:
$methodName = 'UserEnvCP'
$script:nativeMethods = @();
Register-NativeMethod "userenv.dll" "int CreateProfile([MarshalAs(UnmanagedType.LPWStr)] string pszUserSid,`
[MarshalAs(UnmanagedType.LPWStr)] string pszUserName,`
[Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszProfilePath, uint cchProfilePath)";
Add-NativeMethods -typeName $MethodName;
$localUser = New-Object System.Security.Principal.NTAccount("$UserName");
$userSID = $localUser.Translate([System.Security.Principal.SecurityIdentifier]);
$sb = new-object System.Text.StringBuilder(260);
$pathLen = $sb.Capacity;
Write-Verbose "Creating user profile for $Username";
try
{
[UserEnvCP]::CreateProfile($userSID.Value, $Username, $sb, $pathLen) | Out-Null;
}
catch
{
Write-Error $_.Exception.Message;
break;
}
All you need to do is run a command as that user, Windows will create the profile:
psexec.exe -u foobar -p Abcd123! cmd.exe /c exit
https://docs.microsoft.com/en-us/sysinternals/downloads/psexec
As @FrankMerrow posted, on this Stack Overflow question you will find the answer, but the correct is the one from Neck Beard, I'll copy it here.
As @woter324 points out issuing $profile | select * will show you the paths from where PowerShell gets profiles. As stated in the MS documentation:
The profiles are listed in precedence order. The first profile has the highest precedence.
<username>$> $profile | select *
AllUsersAllHosts : C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1
AllUsersCurrentHost : C:\Windows\System32\WindowsPowerShell\v1.0\Microsoft.PowerShell_profile.ps1
CurrentUserAllHosts : C:\Users\<username>\Documentos\WindowsPowerShell\profile.ps1
CurrentUserCurrentHost : C:\Users\<username>\Documentos\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
Length : <will vary>
Those above are mine's, I supose you get something like
CurrentUserAllHosts : H:\WindowsPowerShell\profile.ps1
CurrentUserCurrentHost : H:\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
In order to edit those paths you have two ways
Via regedit
Edit the key with name Personal that you will find under HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
Via PowerShell
I didn't test this one, in the linked thread a user says it has to be tweaked in order to work but I supose it should be easy to get through.
Issue
New-ItemProperty
'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders'
Personal -Value 'Your New Path Here' -Type ExpandString -Force
Either way you have to reboot Power Shell (or windoes terminal) for this to take effect. You can then check again with $profile | select *.
You might also check out this post on Stack Overflow. The best solution offered so far (to my almost identical question) is to change $profile.AllUsersAllHosts to "dot source" another file of your own choosing.
I've seen nothing so far to indicate you can change the default value of $profile itself.