4

Background (OS: Windows 10):

  • I have Powershell script that runs(in background) as SYSTEM

  • Through Powershell script I need to set both Machine and Logged-in User Environment Variables

  • Machine Variables are set using [Environment]::SetEnvironmentVariable('NAME', 'Value', 'Machine') and works as-expected

  • User Variables set using [Environment]::SetEnvironmentVariable('NAME1', 'Value1', 'User') does not work for End user accounts as the process runs as SYSTEM

  • Powershell script execution needs at least one user logged in and this is working fine

I am able to find the logged in user with: $current_user = (Get-WmiObject -Class Win32_ComputerSystem).UserName.Split('\')[1]

I tried using Registry update to set logged-in User Variables but this does not work as expected: Set-ItemProperty -Path 'HKCU:\Environment' -Name 'NAME2' -Value 'Value2' -Force

How can I set Logged-In User Env Variable from powershell script running as SYSTEM?

mklement0
  • 382,024
  • 64
  • 607
  • 775
SagarKC
  • 85
  • 1
  • 8
  • 1
    Search for "powershell impersonate user", that might bring you on track. – zett42 Mar 29 '20 at 10:18
  • I don't think you need to impersonate, you just need to load the user hive into the current registry, see e.g.: [Powershell REG LOAD command not working](https://stackoverflow.com/a/35134100/1701026). Make sure you also **UNLOAD the hive** when you done!. For troubleshooting under the SYSTEM account see [this answer](https://stackoverflow.com/a/51612478/1701026). Also note that you probably have to reload you user session to apply the changes you made. – iRon Mar 29 '20 at 11:44

3 Answers3

4

In order to set a registry value for the currently logged on user (which is not the one that runs the code), you need to find the users SID.

Try this:

# get the domain and username for the currently logged on user
$domain, $userName = (Get-WmiObject -Class Win32_ComputerSystem).UserName -split '\\', 2
# next, get the SID for that current user
$user = [System.Security.Principal.NTAccount]::new($domain, $userName)
$sid  = $user.Translate([System.Security.Principal.SecurityIdentifier]).Value

# set the registry value for this user.
Set-ItemProperty -Path "Registry::HKEY_USERS\$sid\Environment" -Name 'NAME2' -Value 'Value2' -Type String

# See: https://learn.microsoft.com/en-us/dotnet/api/microsoft.win32.registryvaluekind?redirectedfrom=MSDN
# for other RegistryValueKind values for parameter Type
Theo
  • 57,719
  • 8
  • 24
  • 41
3

For troubleshooting scripts running under the SYSTEM account, I am recommend using PSExec, see: this answer.
If you user's registry hive is not yet loaded, you need to load (and Unload it when you're done), see: Powershell REG LOAD command not working.

To find the user's hive (the path is identified by the user's SID) and set the environment variable:

$UserHive = Get-ChildItem -Path 'Registry::\HKEY_USERS' |
    Where-Object {(Test-Path "Registry::$_\Volatile Environment") -and (Get-ItemProperty "Registry::$_\Volatile Environment").USERNAME -eq $Username}

Set-ItemProperty -Path "Registry::$UserHive\Environment" -Name 'NAME2' -Value 'Value3' -Force 
iRon
  • 20,463
  • 10
  • 53
  • 79
0

In addition to the accepted answer, if you are wondering how to get the SID for one of the local system accounts like SYSTEM refer to the table below or follow this link for complete list of Well Known SIDs:

SID Name Description
S-1-5-18 Local System A service account (SYSTEM) that is used by the operating system.
S-1-5-19 NT Authority Local Service
S-1-5-20 NT Authority Network Service

To create a user variable for the local SYSTEM user the command would be as follows:

# set environment variable 'NAME2' for the local SYSTEM user
Set-ItemProperty -Path "Registry::HKEY_USERS\S-1-5-18\Environment" -Name 'NAME2' -Value 'Value2' -Type String
Emil
  • 2,196
  • 2
  • 25
  • 24