How to change specific registry setting for another user in powershell
Asked Answered
T

1

6

Goal:

To edit a specific registry key setting for a specific user, and no others, in powershell.

Known:

OS: Windows 8.1 Embedded Industry Pro (Same as Win 8.1, but with some embedded features)

I can do this manually on the target machine by opening REGEDIT, selecting HKU, then click on File Menu, click on Load Hive, navigate to the user's profile directory, e.g: c:\users\MrEd and when prompted, type in 'ntuser.dat' - import HKEY_CURRENT_USER. The Hive will be loaded into HKU where you can navigate and make necessary modifications.

Summary:

I have a powershell script that returns the SID of the specific user, but when used in context of the registry hive, the hive"is not found" -- so I'm guessing I must be missing a step? How does one "Load Hive" from Powershell? Or am I missing a special, magical, goats-entrails-on-keyboard incantation somewhere?

Param(
    [string]$user= $null
)


Function GetSIDfromAcctName()
{
    Param(
        [Parameter(mandatory=$true)]$userName
    )
    $myacct = Get-WmiObject Win32_UserAccount -filter "Name='$userName'" 
    return $myacct.sid
}

if($user)
{
    $sid = GetSIDfromAcctName $user
    New-PSDrive HKU Registry HKEY_USERS
    $myHiveEntry = Get-Item "HKU:\${sid}"
    Write-Host "Key:[$myHiveEntry]"
}
Taraxacum answered 13/8, 2015 at 22:45 Comment(1)
Looks ok to me, make sure you're use the dir $myHiveEntry from HKU: Location, otherwise it will throw error, add "CD HKU:" before accessing itParian
Q
4

Your existing code should work for a user whose hive is already loaded (like a currently logged in user), but it makes no attempt to load the hive.

I don't know of a way to make a programmatic call to load a hive, but you can shell out to reg.exe.

This ends up being kind of janky. It seems to have issues unloading the hive if it's in use anywhere, so I've put a bunch of crap in place in this sample to try to get rid of stuff that might be holding it open, but in my tests, it can take quite a while before the reg unload command is successful, hence the whole retry portion in the finally block.

This is super unpolished, I just whipped it up on the spot.

Function GetSIDfromAcctName()
{
    Param(
        [Parameter(mandatory=$true)]$userName
    )
    $myacct = Get-WmiObject Win32_UserAccount -filter "Name='$userName'" 
    return $myacct.sid
}

$user = 'someuser'

$sid = GetSIDfromAcctName -userName $user

$path = Resolve-Path "$env:USERPROFILE\..\$user\NTUSER.DAT"

try {
    reg load "HKU\$sid" $path 

    #New-PSDrive -Name HKUser -PSProvider Registry -Root "HKEY_USERS\$sid"

    #Get-ChildItem HKUser:\

    Get-ChildItem Registry::\HKEY_USERS\$sid

} finally {

    #Remove-PSDrive -Name HKUser

    [System.GC]::Collect()
    [System.GC]::WaitForPendingFinalizers()

    $retryCount = 0
    $retryLimit = 20
    $retryTime = 1 #seconds

    reg unload "HKU\$sid" #> $null

    while ($LASTEXITCODE -ne 0 -and $retryCount -lt $retryLimit) {
        Write-Verbose "Error unloading 'HKU\$sid', waiting and trying again." -Verbose
        Start-Sleep -Seconds $retryTime
        $retryCount++
        reg unload "HKU\$sid" 
    }
}

This doesn't use a PS drive, but that code is in there too, commented out.

Note that if you don't name the hive mount point with the SID, you won't actually need the SID at all because you use the username to find the NTUSER.DAT file anyway.

Quicktempered answered 13/8, 2015 at 23:26 Comment(1)
Hi Briantist - this gets me further along. I did notice that even doing this manually with Regedit, it likes to hold onto the NTUSER.DAT file even after it's closed. Fortunately, this is destined to be part of a pre-deployment script so the system gets rebooted after this and other little charmers get implemented. Thank you for your help!Taraxacum

© 2022 - 2024 — McMap. All rights reserved.