generalmx's script collection - Semi-safely merge an old registry with a current one

Discussion in 'Windows 8' started by generalmx, Sep 25, 2014.

  1. generalmx

    generalmx MDL Novice

    Apr 15, 2014
    34
    21
    0
    #1 generalmx, Sep 25, 2014
    Last edited by a moderator: Apr 20, 2017
    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
    
     
  2. generalmx

    generalmx MDL Novice

    Apr 15, 2014
    34
    21
    0
    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...
     
  3. ChaserLee

    ChaserLee MDL Senior Member

    Oct 7, 2014
    437
    93
    10
    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!
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  4. CEW

    CEW MDL Senior Member

    Jan 21, 2011
    296
    155
    10
    #4 CEW, Nov 4, 2014
    Last edited by a moderator: Apr 20, 2017
  5. ChaserLee

    ChaserLee MDL Senior Member

    Oct 7, 2014
    437
    93
    10
    #5 ChaserLee, Nov 5, 2014
    Last edited by a moderator: Apr 20, 2017
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  6. Mr Jinje

    Mr Jinje MDL Expert

    Aug 19, 2009
    1,770
    1,101
    60
    #6 Mr Jinje, Nov 5, 2014
    Last edited by a moderator: Apr 20, 2017
    Freeware not needed.

    Code:
    reg save "hkey_current_user" "B:\NTUSER.DAT"
     
  7. generalmx

    generalmx MDL Novice

    Apr 15, 2014
    34
    21
    0
    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.
     
  8. ChaserLee

    ChaserLee MDL Senior Member

    Oct 7, 2014
    437
    93
    10
    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. o_O
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...