Offline registry editing: Load registry-hive -> delete a key --> unload hive (with Powershell)

This thread ends with an answer advising to answerer to keep using reg.exe instead of powershell:
http://www.eggheadcafe.com/software/aspnet/33496899/-loading-registry-hive.aspx
Our hives are on a profile-share on the same server, so I wouldn't have to check for operating system etc.

Maybe VBScript executed in a loginscript is better?

LVL 1
jmateknikAsked:
Who is Participating?
 
RobSampsonCommented:
Hi, have a look at the code here:
http://www.experts-exchange.com/Programming/Languages/Visual_Basic/VB_Script/Q_22609815.html#a19222158

That wraps up the Reg Load and Reg Unload commands in VBScript, loading each ntuser.dat in Documents and Settings.

Read my comments about running the scripts and see if it helps.

Regards,

Rob.
0
 
brumby2Commented:
I'm not sure exactly what you're after but here is some code that I have used in the past.
Also - keep in mind that you need to be running 2008 R2 on your DC's to use Powershell as a startup script..
checking for the OS is simple.. Just google it.


$checkrr = (Get-WmiObject win32_service -computername $computername | where-Object { ($_.name -eq "remoteregistry")})
                                          
                                          if ($checkrr.state -eq 'Stopped')
                                                {      
                                                      write-host "Remote Registry Service is Stopped.."
                                                      Write-Host "Starting.."
                                                      $checkrr.startservice()
                                                      ""
                                                }


                                                $openreg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $computername)
                                                $regkey = $openreg.OpenSubKey("SOFTWARE\Support")
                                                
                                                Add-Content D:\scripts\CheckBuildREG\done.txt "$computername"
                                                
                                                if (!$regkey)
                                                      { Write-Host "Key doesnt exist"
                                                            Add-Content D:\scripts\CheckBuildREG\nonsoe.txt "$computername"
                                                            exit      
                                                      }
                                                $reg = $regkey.GetValueNames()
                                                
                                                
                                                if ($reg)
                                                      {
                                                            Write-Host "key exists"
                                                            Add-Content D:\scripts\CheckBuildREG\soe.txt "$computername"
                                                            exit
                                                      }
0
 
jmateknikAuthor Commented:
We're not using an Windows Server 2008 R2 DC so its not possible via logonscript. BUT - if off-line editing were possible that wouldn't be a problem, and it would the best solution to edit them off-line. I can run scripts from an administrator-context, so I would be able to run this via task scheduler.

I need to open a lot of registries (NTUser.dat) located in the same folder like this:
   [profile1]
      [Application Data]
      [Favorites]
      [..]
      NTUser.dat
   [profile2]
      [Application Data]
      [Favorites]
      [..]
      NTUser.dat
   [ .. ]

I can do this manually by:  
Opening regedit -> mark HKEY_local_machine ->file-menu/'Load hive' -> name the hive -> do some editing --> mark the named hive -> File-menu/'Unload hive'.
I would love to be able to handle this offline editing
0
How do you know if your security is working?

Protecting your business doesn’t have to mean sifting through endless alerts and notifications. With WatchGuard Total Security Suite, you can feel confident that your business is secure, meaning you can get back to the things that have been sitting on your to-do list.

 
jmateknikAuthor Commented:
Looks like there's put a lot of work in that script.

Its not clear to me though, where in the script the ntuser.dat is loaded and unloaded - to me (being no VB-shark) it looks like running registries are opened from individual running workstations.

Could you help me picking out the essentials?
0
 
jostranderCommented:
Hi all,

I don't have a powershell sample, but here's another reg.exe method that you can use on a remote PC (provided that the user is not logged in*).  

*As you may know, If the user is logged in to the host, you can access their registry without reg.exe since it will appear under HKEY_USERS\s-1-5-21....
ON ERROR RESUME NEXT

strComputer="XPCOMPUTER1"
strUser="Administrator"


strTitle="Remote Registry Load"

myHive="\\" & strComputer & "\c$\Documents and Settings\" & strUser & "\NTUSER.DAT"


Set WshShell=CreateObject("Wscript.Shell")


'Pick a nice name for the loaded registry
myKey="HKLM\" & strComputer & "_" & strUser


'load the remote hive
WshShell.run "reg load " & myKey & " " & Chr(34) & myHive & Chr(34) ,0,true


	
'See if the reg loaded successfully
If regExists(myKey & "\") then
	msgbox strComputer & " HKEY_CURRENT_USER for " & strUser & " loaded to:" & _
		vbCrLf & vbCrLf & "HKLM\" & strComputer & "_" & strUser ,vbInformation,strTitle
Else
	msgbox "Failed to load remote registry hive from " & strComputer,vbExclamation,strTitle
	wscript.quit
End If


'Create a key and value
WshShell.RegWrite myKey & "\NewKey\MyValue", "Hello World"

'Read the value
test=WshShell.RegRead(myKey & "\NewKey\MyValue")
msgbox "This was just written to " & myKey & "\NewKey\MyValue:" & vbCrLf & vbCrLf & test,vbInformation,strTitle

'Delete the key we made
WshShell.RegDelete myKey & "\NewKey\"
msgbox "Just deleted the key:  " & myKey & "\NewKey\",vbInformation,strTitle


'Unload the registry
While regExists(myKey & "\")
	WshShell.run "reg unload " & myKey ,0,false
	wscript.sleep 1000
	count=count+1
	If count=10 then
		ret=msgbox("Unable to unload registry.  If you have it open, please close." & _
			vbCrLf & vbCrLf & "Try again?",vbQuestion+vbYesNo,strTitle)
		If ret=vbYes then
			count=0
		Else
			wscript.quit
		End If
	End If
Wend

If NOT regExists(myKey & "\") then msgbox "Successfully unloaded " & myKey ,vbInformation,strTitle


Function regExists(regKey)
	ON ERROR RESUME NEXT
	regExists=WshShell.RegRead(regKey)
	if NOT isEmpty(regExists) then regExists=true
	if Hex(Err) = "80070002" then regExists=false
End Function

Open in new window

0
 
RobSampsonCommented:
Joe's code may be better if you are targeting a specific user on the remote computer.  Is that enough, or were you after each profile on the remote computer?  If that's the case, I'll step you through the code I pointed to...

Regards,

Rob.
0
 
jmateknikAuthor Commented:
You gave me the pieces to create what I basically needed, and I am confident that I can get the rest from here on (1. Doing something with the loaded hive, 2. Cycling through all profiles in a profilefolder with foreach).

reg.exe was basically the tool to use.

If anyone should want to get the result please leave a note and ill post it sometime in the future.
Thanks to all who helped.
$ProfilesFolder = "<path>"
$UserProfile	= "Default User"
$TempHive		= "HKLM\TempHive"

function RegLoad () {
	reg load $TempHive "$ProfilesFolder\$UserProfile\NTUSER.DAT"
}

function RegUnload () {
	reg unload HKLM\TempHive
}

RegLoad
#<Modify here>
RegUnload

Open in new window

0
 
jmateknikAuthor Commented:
Since I asked for Powershell and not VBScript and if giving the grade 'Excellent' should make sense I am giving it a 'Good' (which is between Excellent and average).
0
 
jostranderCommented:
Here's a sample I was working on before the answer was accepted...
$strComputer="SERVER1"
$strUser="Administrator"

#path to your hive
$myHive="\\" + $strComputer + "\c$\Documents and Settings\" + $strUser + "\NTUSER.DAT"

#Pick a nice name for the loaded registry
$myKey=$strComputer + "_" + $strUser

#load the remote hive
$CMD="reg load HKLM\" + $myKey + " `""+$myHive+"`""
invoke-expression $CMD


#Pause
Clear-Host
Write-Host
Write-Host "Open REGEDIT to view remote registry"
Write-Host
Write-Host "HKLM\$myKey"
Write-Host
Write-Host "Press any key to continue..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

#Add a key to the new reg
New-Item -Path hklm:"$myKey\_DeleteMe"

#Pause
Clear-Host
Write-Host
Write-Host "Added key:  HKLM\$myKey\_DeleteMe"
Write-Host
Write-Host "Go verify in REGEDIT"
Write-Host
Write-Host "Press any key to continue..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

#Remove the new key
Remove-Item -Path hklm:"$myKey\_DeleteMe" -Recurse

#Pause
Clear-Host
Write-Host
Write-Host "Deleted key:  HKLM\$myKey\_DeleteMe"
Write-Host
Write-Host "Go verify in REGEDIT"
Write-Host
Write-Host "Press any key to continue..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

Clear-Host
Write-Host
Write-Host "Close Regedit and Press any key to continue..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

Start-Sleep -s 1

#unload the remote hive
#$CMD="reg unload HKLM\" + $myKey
#echo $CMD
#invoke-expression $CMD
#For some reason it gets locked... this way works better
cmd /c start reg unload "HKLM\$myKey"

Open in new window

0
 
jostranderCommented:
It would be nice to find a way to do it without reg.exe.  If you find a way, please let me know.

Thanks!
Joe
0
 
jostranderCommented:
Hmm, I tried doing a DLLImport of advapi32.dll to get the RegLoadKey method.  So far no luck.

I peeked at the source code for RegeditPE and it looks like even they are using reg.exe.
0
 
jostranderCommented:
Ooooh, got the DLL import working.  I have to take off for the day... but I'll leave you with what is working great for me.  The only issue I have is unloading the registry after modification... a little unpredictable.

I haven't tested on XP yet.. only Win7.

Enjoy!
Joe
$strComputer="Server1"
$strUser="Administrator"

Clear-Host

#path to your hive
$myHive="\\" + $strComputer + "\c$\Documents and Settings\" + $strUser + "\NTUSER.DAT"


#Pick a nice name for the loaded registry
$myKey=$strComputer + "_" + $strUser


#RegLoadKey
#RegUnLoadKey
#http://support.microsoft.com/kb/297060
#http://msdn.microsoft.com/en-us/library/ms724889(VS.85).aspx

# allow script to set ownership
# requires PowerShell Community Extensions
# http://www.codeplex.com/PowerShellCX
$SeRestore = new-object Pscx.Interop.TokenPrivilege "SeRestorePrivilege", $true
Set-Privilege $SeRestore


#---------------------------------------------------------------    
# Import the functions from DLL
#---------------------------------------------------------------    
$sig1 = @'
[DllImport("advapi32.dll", SetLastError=true)]
public static extern int RegLoadKey(
    uint hKey,
    string lpSubKey,
    string lpFile);
'@

$sig2 = @'
[DllImport("advapi32.dll", SetLastError=true)]
public static extern int RegUnLoadKey(
    uint hKey,
    string lpSubKey);
'@


$type1 = Add-Type -MemberDefinition $sig1 -Name Win32Utils `
    -Namespace RegLoadKey -Using System.Text -PassThru

$type2 = Add-Type -MemberDefinition $sig2 -Name Win32Utils `
    -Namespace RegUnLoadKey -Using System.Text -PassThru
    

#not sure if it HAS to be UINT...
$HKLM = [uint32]0x80000002L
$HKU = [uint32]0x80000003L

#---------------------------------------------------------------    
#	Load the registry file
#---------------------------------------------------------------    
$result = $type1::RegLoadKey($HKLM, $myKey, $myHive)
if ($result -eq 0) {
	Write-Host 
	Write-Host "Registry file loaded to:  $myKey"
	Write-Host 
} else {
	Write-Host "Unable to load registry file."
	exit
}


#---------------------------------------------------------------    
#	Stop to verify Registry loaded
#---------------------------------------------------------------  
Clear-Host
Write-Host
Write-Host "Open REGEDIT to view remote registry"
Write-Host
Write-Host "HKLM\$myKey"
Write-Host
Write-Host "Press any key to continue..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")


#---------------------------------------------------------------    
#	Add a key to the new reg
#---------------------------------------------------------------  
New-Item -Path hklm:"$myKey\_DeleteMe"



#---------------------------------------------------------------    
#	Stop to verify New key added
#---------------------------------------------------------------  
Clear-Host
Write-Host
Write-Host "Added key:  HKLM\$myKey\_DeleteMe"
Write-Host
Write-Host "Go verify in REGEDIT"
Write-Host
Write-Host "Press any key to continue..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")



#---------------------------------------------------------------    
#	Remove the new key
#---------------------------------------------------------------  
Remove-Item -Path hklm:"$myKey\_DeleteMe" -Recurse


#---------------------------------------------------------------    
#	Stop to verify New key deleted
#--------------------------------------------------------------- 
Clear-Host
Write-Host
Write-Host "Deleted key:  HKLM\$myKey\_DeleteMe"
Write-Host
Write-Host "Go verify in REGEDIT"
Write-Host
Write-Host "Press any key to continue..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")


#---------------------------------------------------------------    
#	Prompt to close regedit
#--------------------------------------------------------------- 
Clear-Host
Write-Host
Write-Host "We're all done here!"
Write-Host 
Write-Host "Close Regedit, then Press any key to continue..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")



#---------------------------------------------------------------    
#	Unload the registry file
#	Seems to only work if it wasn't modified
#--------------------------------------------------------------- 
$result = $type2::RegUnLoadKey($HKLM, $myKey)
if ($result -eq 0) {
	Write-Host 
	Write-Host "Registry file unloaded successfully."
	Write-Host 
} else {
	cmd /c start reg unload "HKLM\$myKey"
	Start-Sleep -s 15
	$test = test-path HKLM:\$myKey
	if ($test) {
		Write-Host "ERROR:  Unable to unload registry file."
		Write-Host "run this command:"
		Write-Host "reg unload HKLM\$myKey"
	} else {
		Write-Host 
		Write-Host "Registry file unloaded successfully (2nd try)."
		Write-Host 
	}


	
}

Open in new window

0
 
jmateknikAuthor Commented:
Or waw...gotta look into your code

I've made some myself (its not finished - will end up being able to handle single profile, entire profilefolder or partly profilefolder via list)
#Profile
$ProfilesPath 	= "<path>"

#Profilehiveloading (Cycling folder or running through a list or just a single user)
#$UserProfile	= "Default User"
#$UserList 		= "Default User"
#$UserProfile   = "Default User"

$TempHive		= "HKLM\TempHive"
$PSTempHive 	= $TempHive.Replace("HKLM","HKLM:")

# Registry creation
$Key			= "$PSTempHive\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap"
$KeyName 		= "IEHarden" 
$ValueType 		= "DWORD" 
$Value 			= 0  

# Functions
function RegLoad () {
	reg load $TempHive "$ProfilesPath\$UserProfile\NTUSER.DAT"
}

function RegUnload () {
	reg unload HKLM\TempHive
}

function CycleProfilesFolder (){
	$ProfilesFolders = dir $ProfilesPath -force | where { $_.PSIsContainer } |select name	
	$ProfilesFolders | 
		foreach {
			Write-Host Loading profile: $_.name
			Regload
			Write-Host Unloading profile: $_.name
			RegUnload
		}
}

Function Get-RegistryValue($Regkey, $Name) {
     Get-ItemProperty "Registry::$key" $Name | Select-Object -expandProperty $value
}

Function Test-RegistryValue($Regkey, $Value) {
	Get-ItemProperty $regkey $value -ErrorAction SilentlyContinue |
		Out-Null
	$?
}

function Create-Key([string]$RegKey, [string]$Name, [string]$ValueType, $Value) {
	Write-Host "Creating $ValueType with value '$($Value.tostring())' in $Key"
	New-ItemProperty $Key -Name $Name -Value $Value -PropertyType $ValueType
	if (test-registryValue $key "IEHarden")
		{ Write-Host "Value successfully created" }
	else { Write-Host "Value not created" }
}

function CreateKeyIfNotThere(){
	if (test-registryValue $key "IEHarden") {
		Get-RegistryValue $key "IEHarden"	
	}else{
		Create-key $Key $KeyName $ValueType $Value  	
	}	
}

cls
#RegLoad
CreateKeyIfNotThere


#Get-RegistryValue '$PSTempHive\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap' IEHarden

Open in new window

0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.