Helping a relative who had enough corruption to stop Windows from booting, but not enough to make the files inaccessible, I found while I couldn't repair or refresh Windows, I could do a fresh install and then copy back the installation status of his ~300+ Steam games and other apps through merging specific parts of the old Windows registry with the new installation's, and since neither the REG command nor any utility I found could do this without overwriting everything, I made this little Windows batch script. It requires sed for Windows, since otherwise using variable substitution wouldn't work in this case, and Windows batch doesn't have any other tools for this type of pattern matching & substitution. sed for Windows from GnuWin32 is pretty portable anyway, only needing sed.exe and its accompanying DLLs. EDIT: The new version no longer requires anything extra. This'll probably be the final version unless someone finds a problem or requests a feature. As far as I know this should work on all versions of Windows that include the REG command, though I've only personally tested it on Windows 8 and Windows 7. Also note you must use the "short name" of HKEY_LOCAL_MACHINE and HKEY_USERS for some reason (HKLM and HKU, respectively) with the REG command. Newest Version (9-26-2014): Code: @echo off :: This batch files copies from an offline Windows registry file into the current Windows registry only keys :: that don't exist in the destination, merging the information instead of overwriting it. :: Theoretically, you should be able to use this to merge settings and states from an old Windows :: installation into a fresh one. :: By Gen 9-26-2014 :: :: Note: For automation you may give anything for a 3rd argument to prevent pausing. :: :: Changelog :: 9-26-2014 Removed sed dependency and other small enhancements. :: 9-24-2014 Initial version. Requires sed. :: SETLOCAL EnableDelayedExpansion REM Check arguments. IF NOT [%~1]==[] IF NOT [%~2]==[] GOTO :start REM Usage information. echo Usage: %~nx0 "registry file" "path to copy" echo. echo Example: %~nx0 "E:\Backup\Users\Owner\NTUSER.DAT" "HKU\S-1-5-21-1381051429-2129439637-628306816-1000\WoW6432Node\Microsoft" echo. echo In the above example, we want to copy everything in "WoW6432Node\Microsoft" echo from the backup user registry file NTUSER.DAT to the same location for echo the user id S-1-5-21-1381051429-2129439637-628306816-1000 GOTO :done :start IF NOT EXIST "%~f1" ( echo ** ERROR: File [%~f1] does not seem to exist GOTO :done ) REM Break up 2nd argument into rootkey, substitution key, and rest of path. set _rootkey= set _subkey= set _relpath= FOR /F "tokens=1,2,* delims=\" %%A IN ("%~2") DO ( set _rootkey=%%A set _subkey=%%B IF NOT [%%C]==[] set _relpath=\%%C ) IF NOT [!_rootkey!]==[] IF NOT [%_subkey%]==[] GOTO :continue1 echo ** ERROR: Cannot parse given registry path [%~2] GOTO :done :continue1 echo ** Loading hive located at [%~f1] to [!_rootkey!\TempHive] echo ** Using relative path: [!_relpath!] echo ** Copying to: [!_rootkey!\%_subkey%!_relpath!] REM You may give a 3rd argument to prevent pausing. IF [%~3]==[] ( echo ** Ready to load registry - press any key to continue, or use CTRL+C to abort pause >Nul 2>&1 ) REM Load registry and check REM vv Boolean value set _loaded=0 REG LOAD "!_rootkey!\TempHive" "%~1" && echo ** Offline registry successfully loaded. && set "_loaded=1" IF NOT !_loaded! EQU 1 ( echo ** ERROR: Offline registry not successfully loaded. Aborting. REG UNLOAD "!_rootkey!\TempHive" >Nul 2>&1 GOTO :done ) set _fcount=0 set _notfcount=0 set _sourcepath= set _destpath= REM FOR /F "delims=" %%A IN ('REG QUERY "!_rootkey!\TempHive!_relpath!" ^| sed.exe -n "s#\(H[^\\]*\)\\TempHive\\\(.*\)$#\1\\!_subkey!\\\2#p"') DO ( FOR /F "tokens=1,2* delims=\" %%A IN ('REG QUERY "!_rootkey!\TempHive!_relpath!"') DO ( REM echo Looking for key [%%A]... set _sourcepath=%%A\%%B\%%C set _destpath=!_sourcepath:%%A\TempHive\%%C=%%A\%_subkey%\%%C! IF NOT [!_destpath!]==[] IF NOT [!_destpath!]==[!_sourcepath!] ( REM vv Boolean value set _found=0 REM We skip keys where the destination exists. REG QUERY "!_destpath!" >Nul 2>&1 && set "_found=1" IF !_found! EQU 1 ( set /A "_fcount+=1" REM echo Skipping key [%%A]... ) ELSE ( REM Key does NOT exist in destination. set /A "_notfcount+=1" echo Copying [!_sourcepath!] to [!_destpath!]... REM Put "echo" in front of the below command if you just want to simulate. REG COPY "!_sourcepath!" "!_destpath!" /s /f ) ) ELSE ( echo ** Error substituting [%_subkey%] in key [%%A\%%B\%%C] ) ) echo ** Keys copied: !_notfcount! echo ** Keys NOT copied: !_fcount! REG UNLOAD "!_rootkey!\TempHive" >Nul 2>&1 && echo ** Offline registry successfully unloaded. echo ** Done. :done Previous Version: Code: @echo off :: This batch files copies from an offline Windows registry file into the current Windows registry only keys :: that don't exist in the destination, merging the information instead of overwriting it. :: By Gen 9-25-2014 :: :: Note: This batch file requires sed for Windows, such as the one from GnuWin32. :: SETLOCAL EnableDelayedExpansion GOTO :start :usage echo Usage: %~nx0 "registry file" "path to copy" echo. echo Example: %~nx0 "E:\Backups\Users\Owner\NTUSER.DAT" "HKU\S-1-5-21-1381051429-2129439637-628306816-1000\WoW6432Node\Microsoft" echo In the above example, we want to copy everything in "WoW6432Node\Microsoft" from the user's registry, copying it to echo HKU\S-1-5-21-1381051429-2129439637-628306816-1000\WoW6432Node\Microsoft GOTO :done :start IF [%~1]==[] GOTO :usage IF [%~2]==[] GOTO :usage IF NOT EXIST "%~f1" ( echo ** ERROR: File [%~f1] does not seem to exist GOTO :done ) set _rootkey= set _subpath= set _regpath= FOR /F "tokens=1,2,* delims=\" %%A IN ("%~2") DO ( set _rootkey=%%A set _subpath=%%B set _regpath=\%%C ) IF [!_regpath!]==[] ( echo ** ERROR: Cannot parse given registry path [%~2] GOTO :done ) echo ** Loading hive located at [%~f1] to [!_rootkey!\TempHive] echo ** Using relative path: [!_regpath!] echo ** Copying to: [!_rootkey!\!_subpath!!_regpath!] set _loaded=0 REG LOAD "!_rootkey!\TempHive" "%~1" && echo ** Offline registry successfully loaded. && set "_loaded=1" IF NOT !_loaded! EQU 1 ( echo ** ERROR: Offline registry not successfully loaded. Aborting. REG UNLOAD "!_rootkey!\TempHive" >Nul 2>&1 GOTO :done ) set _fcount=0 set _notfcount=0 FOR /F "delims=" %%A IN ('REG QUERY "!_rootkey!\TempHive!_regpath!" ^| sed.exe -n "s#\(H[^\\]*\)\\TempHive\\\(.*\)$#\1\\!_subpath!\\\2#p"') DO ( REM echo Looking for key [%%A]... REM vv Boolean set _found=0 REG QUERY "%%A" >Nul 2>&1 && set "_found=1" IF !_found! EQU 1 ( set /A "_fcount+=1" REM echo Skipping key [%%A]... ) ELSE ( set /A "_notfcount+=1" set _sourcekey='' FOR /F "delims=" %%G IN ('echo %%A ^| sed.exe -n "s#\(H[^\\]*\)\\!_subpath!\\\(.*\) $#\1\\TempHive\\\2#p"') DO ( set _sourcekey=%%G ) IF NOT [!_sourcekey!]==[] ( echo Copying [!_sourcekey!] to [%%A]... REG COPY "!_sourcekey!" "%%A" /s /f ) ) ) echo ** Keys copied: !_notfcount! echo ** Keys NOT copied: !_fcount! REG UNLOAD "!_rootkey!\TempHive" >Nul 2>&1 && echo ** Offline registry successfully unloaded. echo ** Done. :done
I'd just like to add I've been further successful using this multiple times to migrate old Windows installations of programs where I can't get ahold of the install media or activation info and can't repair Windows, to fresh installs of Windows (previously we had to use a paid product). Right now this is in the Windows 8 forum, but I think it's good enough to go into the MDL Project forum, as it doesn't actually require or depend on Windows 8 and could even theoretically be used with as old as Windows XP. Maybe I should make this into an AutoIT script, to give it a nice GUI...
Sounds like a VERY useful script to have on hand. Just one question... how can I make a "backup user registry file NTUSER.DAT", Because when I use regedit to do an export of the registry, it wants to save it as a .reg file, not a .DAT file. When I try to copy the NTUSER.DAT file, it won't let me, saying the file is locked and in use. So, as newb as this sounds, how do I get a copy of my .DAT file onto another hard drive for future useage? Thanks!
You can also just copy the file as a different user --- the current user's registry (and the current system registry for all users) will always be in-use while logged in to a particular user.
Thanks, but regbak works really well for me, so I'll stick with using that. Besides, I only have one user account on this OS.