Link to home
Start Free TrialLog in
Avatar of jmateknik
jmateknikFlag for Denmark

asked on

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?

SOLUTION
Avatar of brumby2
brumby2

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of jmateknik

ASKER

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
ASKER CERTIFIED SOLUTION
Avatar of RobSampson
RobSampson
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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?
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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.
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

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).
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

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
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.
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

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