Sign in to follow this  
Followers 0
DrLarch

Yet another _RegWriteAllUsers

7 posts in this topic

Just wanted to post my _RegWriteAllUsers script (started off modifying the code >here, but ended up pretty much being a rewrite for my own purposes). I'd ultimately like to be able to use "Larry's" >code (DllCall) to load/unload hives (more elegant) instead of RunWaits, but haven't had the chance to track this one all the way down and figure it out, so if anyone knows this off-hand I'd appreciate it.

Anyway, the script will do multiple entries (input is an array), but has only been designed/tested on Win7/64. Account names can be filtered out with multiple search terms. One thing I'm wondering about regarding coding techniques is how #includes are properly done within a function.

Script:

#include-once

; #FUNCTION# ========================================================================================================================
; Name...........: _RegWriteAllUsers
; Description ...: Writes multiple registry entries to local user accounts (filterable).
; Syntax.........: _RegWriteAllUsers($InputArray)
; Parameters ....: $InputArray - Array containing registry path, key name, key type, data and filter
;                  Array is two-dimensional, at least two rows by five columns ([2][5]).
;                  First row & column [0][0] contains row count (updated by the function) but must be declared in addition to
;                  subsequent data rows.
;                  Subsequent rows are data: Column [0]:Registry path relative to HKCU\ or HKEY_USERS\{NAME]\
;                                                       Do NOT include leading backslash!
;                                            Column [1]:Key Name
;                                            Column [2]:Key Type: "REG_SZ", "REG_MULTI_SZ", "REG_EXPAND_SZ", "REG_DWORD", "REG_QWORD",
;                                                       or "REG_BINARY"
;                                            Column [3]:Data
;                                            Column [4]:Filter search terms to remove user names with substrings that match,
;                                                       semicolon delimited (ie. "example1;example2"). Entry in the first row
;                                                       of the array is only entry used.
; Author ........: DrLarch
; ===================================================================================================================================

Func _RegWriteAllUsers($InputArray)
    #include <_RegEnumKeyValEx.au3>
    ;_RegEnumKeyValEx by DXRW4E found at:
    ;http://www.autoitscript.com/forum/topic/144234-regenumkeyvalex-regenumkeyex-regenumvalex/
    #include <Array.au3>

    $InputArray[0][0] = UBound($InputArray, 1) - 1;Correct row count

    ;Pull profile list from registry -----------------------------------------------
    $ProfileKey = "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"

    $aProfileList = _RegEnumKeyEx($ProfileKey, 1)

    $aHKUSList = _RegEnumKeyEx("HKEY_USERS", 1)
    ;_ArrayDisplay($aHKUSList,"HKEY_USERS")

    Local $aKill[1]
    $aKill[0] = 0

    ;Remove profiles from list that don't have a GUID ------------------------------
    For $i = 1 To $aProfileList[0]
        Local $sGUIDTest = RegRead($aProfileList[$i], "Guid")
        If @error <> 0 Then
            _ArrayAdd($aKill, $i)
            $aKill[0] += 1
        EndIf
    Next

    _ArrayDelete($aProfileList, $aKill)
    $aProfileList[0] = UBound($aProfileList) - 1


    ;Change array $aProfileList to ProfileImagePath --------------------------------
    Local $aKill[1]
    $aKill[0] = 0

    For $i = 1 To $aProfileList[0]
        $aProfileList[$i] = RegRead($aProfileList[$i], "ProfileImagePath")
        If @error <> 0 Then
            _ArrayAdd($aKill, $i)
            $aKill[0] += 1
        EndIf
    Next

    _ArrayDelete($aProfileList, $aKill)
    $aProfileList[0] = UBound($aProfileList) - 1


    ;Remove user names by filter----------------------------------------------------
    Local $aKill[1], $aKillSearchTerms[1]
    $aKill[0] = 0
    $aKillSearchTerms[0] = 0


    ;Remove currently logged in user (add to $sKillFilter), will handle via HKCU
    $sKillFilter = $InputArray[1][4]

    If StringLen($sKillFilter) > 0 Then
        $sKillFilter = $sKillFilter & ";" & @UserName
    Else
        $sKillFilter = @UserName
    EndIf


    $aKillSearchTerms[0] = _ArrayAdd($aKillSearchTerms, $sKillFilter, 1, ";")
    ;_ArrayDisplay($aKillSearchTerms,"Search Terms")


    For $i = 1 To $aProfileList[0]
        For $j = 1 To $aKillSearchTerms[0]
            ;MsgBox(0,"test","Looking for: " & $aKillSearchTerms[$j] & " in: " & $aProfileList[$i])

            If StringInStr($aProfileList[$i], $aKillSearchTerms[$j]) <> 0 Then
                ;MsgBox(0,"test","Found: " & $aKillSearchTerms[$j] & " in: " & $aProfileList[$i])
                _ArrayAdd($aKill, $i)
                $aKill[0] += 1
                ExitLoop
            EndIf
        Next
    Next

    _ArrayDelete($aProfileList, $aKill)
    $aProfileList[0] = UBound($aProfileList) - 1

    ;_ArrayDisplay($aProfileList,"After Filter")


    ;Double check that ntuser.dat files actually exists-----------------------------
    ;probably not necessary, but just in case
    Local $aKill[1]
    $aKill[0] = 0

    For $i = 1 To $aProfileList[0]
        Local $sNTUser = FileExists($aProfileList[$i] & "\NTUSER.DAT")
        If $sNTUser = 0 Then
            _ArrayAdd($aKill, $i)
            $aKill[0] += 1
        EndIf
    Next

    _ArrayDelete($aProfileList, $aKill)
    $aProfileList[0] = UBound($aProfileList) - 1


    ;Create new $aProfileUserList array from $aProfileList to incorporate user names---------------------
    Local $aFullList[UBound($aProfileList)][2] = [[0, ""]]
    $aFullList[0][0] = $aProfileList[0]

    For $i = 1 To $aProfileList[0]
        $aFullList[$i][0] = $aProfileList[$i]
        $aPathSplit = StringSplit($aProfileList[$i], "\")
        $aFullList[$i][1] = $aPathSplit[UBound($aPathSplit) - 1]
    Next

    ;Add DEFAULT user to $aFullList-------------------------------------------------
    _ArrayAdd($aFullList, "C:\Users\Default|Default8a7h6u8x9u0")
    $aFullList[0][0] += 1

    ;_ArrayDisplay($aFullList)


    ;Load Hives---------------------------------------------------------------------
    $errloop = 0

    Do
        For $i = 1 To $aFullList[0][0]
            RunWait('reg load "HKEY_USERS\' & $aFullList[$i][1] & '" "' & $aFullList[$i][0] & '\NTUSER.DAT"', "", @SW_HIDE)
            Sleep(100)
        Next

        Sleep(1000)
        $aHKUSListCheck = _RegEnumKeyEx("HKEY_USERS", 1)

        If $errloop > 5 Then
            MsgBox(0, "Error", "All hives didn't load - retrying...")
            ExitLoop
        EndIf

        $errloop += 1

    Until $aHKUSListCheck[0] = $aHKUSList[0] + $aFullList[0][0]

    ;MsgBox(0,"test","Loaded...")

    ;Write changes-------------------------------------------------------------------
    For $i = 1 To $aFullList[0][0]
        For $l = 1 To $InputArray[0][0]
            RegWrite("HKEY_USERS\" & $aFullList[$i][1] & "\" & $InputArray[$l][0], $InputArray[$l][1], $InputArray[$l][2], $InputArray[$l][3])
        Next
    Next

    ;Write to Current User
    For $l = 1 To $InputArray[0][0]
        RegWrite("HKCU\" & $InputArray[$l][0], $InputArray[$l][1], $InputArray[$l][2], $InputArray[$l][3])
    Next

    ;MsgBox(0,"test","Written...")


    ;Unload Hives--------------------------------------------------------------------
    Do
        For $i = 1 To $aFullList[0][0]
            RunWait('reg unload "HKEY_USERS\' & $aFullList[$i][1] & '"', "", @SW_HIDE)
            Sleep(100)
        Next

        Sleep(1000)
        $aHKUSListCheck = _RegEnumKeyEx("HKEY_USERS", 1)

        If $errloop > 5 Then
            MsgBox(0, "Error", "Warning: Not all hives could be unloaded properly!")
            ExitLoop
        EndIf

        $errloop += 1

    Until $aHKUSListCheck[0] = $aHKUSList[0]

EndFunc   ;==>_RegWriteAllUsers

Usage:

$sHexStr = '500044004600430072006500610074006f00720000000000000000000000000000000000000000000000000000' & _
'0000000000000000000000000000000000000001040006dc005c0353ef8101010001009a0b3408640001000f005802020001' & _
'005802030001004c006500740074006500720000000000000000000000000000000000000000000000000000000000000000'

$bBinary=Binary('0x'&$sHexStr)

Dim $RegArray[3][5] = _
                    [ _
                    [0,"","","",""], _
                    ["Printers\DevModePerUser","Printer1","REG_BINARY",$bBinary,"sa_smp"], _
                    ["Printers\DevModes2","Printer1","REG_BINARY",$bBinary,""] _
                    ]


_RegWriteAllUsers($RegArray)

It works fine for my purposes, and feedback is appreciated. Hopefully it's useful...

Share this post


Link to post
Share on other sites



"One thing I'm wondering about regarding coding techniques is how #includes are properly done within a function."

What do you mean by that?

If you mean conditional includes, that is not possible, if you put #include directive in a function, you run the risk of nested functions which are not allowed in AutoIt3.


AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Share this post


Link to post
Share on other sites

Does this belong in the Example script forum DrLarch?  Let me know and I'll move it.


Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Share this post


Link to post
Share on other sites

"One thing I'm wondering about regarding coding techniques is how #includes are properly done within a function."

What do you mean by that?

If you mean conditional includes, that is not possible, if you put #include directive in a function, you run the risk of nested functions which are not allowed in AutoIt3.

 

Ok, so it's not possible or I run the risk of nested functions which aren't allowed anyway (won't compile, I'm assuming). So then it really isn't an issue, it seems. I wasn't really wondering for my sake, but anyone else who uses the code. I guess if they received an error then the include within my function would need to be moved/deleted due to the conflict.

 

Does this belong in the Example script forum DrLarch?  Let me know and I'll move it.

 

Sure, I guess. Perhaps I should've posted there first, but wanted feedback as well, hence the post here.

Share this post


Link to post
Share on other sites

I could really make use of a strong working RegWriteAllUsers.  I have a script I made that loads/unloads hives but I never polished it off.

I'll throw my code in just incase it helps in any way.   I later modified this to give me an input box so I could type in the name of the profile I wanted to add keys too, and never got around to it but was going to set it up to update all profiles in a loop.

One of the strange issues I had is that the hive would not always unload so as I was testing the script I would get failure to load the hive, and that was because it never finished unloading from the last run.  So that is why I had that little Do Until loop at the end for unloading.  Once I put that into place this was working perfectly for me. 

#RequireAdmin

$pHive = "HKEY_USERS\Temp\" ;Path\Name of Loaded Hive

Run(@ComSpec & " /c reg.exe load HKU\Temp C:\Users\Default\NTUSER.dat")

Sleep(1000)

$RegTest = RegRead("HKEY_USERS\Temp\Environment", "Temp")


If $RegTest <> "" Then

#Region Cache Terminal
RegWrite($pHive & "Software\InterSystems\Cache Terminal", "LastComm", "REG_SZ", "Winsock")
RegWrite($pHive & "Software\InterSystems\Cache Terminal", "DisableMouse", "REG_SZ", "0")
RegWrite($pHive & "Software\InterSystems\Cache Terminal", "ANSIColor15", "REG_SZ", "255,255,255")
#EndRegion Cache Terminal

#Region Cache Terminal\Winsock
RegWrite($pHive & "Software\InterSystems\Cache Terminal\Winsock", "numnodes", "REG_SZ", "2")
RegWrite($pHive & "Software\InterSystems\Cache Terminal\Winsock", "Port1", "REG_SZ", "23")

Do
    Sleep(200)
    Run(@ComSpec & " /c reg.exe unload HKU\Temp")
    RegRead("HKEY_USERS\Temp\Environment", "Temp")
Until @Error <> ""

MsgBox(0, "Black Magic Installer", "Casewatch Settings Installed for Default User Profile")
#EndRegion Cache Terminal\Winsock
Else
    MsgBox(0, "Black Magic Installer", "Could not load the Default User Hive")
EndIf

Share this post


Link to post
Share on other sites

One of the strange issues I had is that the hive would not always unload so as I was testing the script I would get failure to load the hive, and that was because it never finished unloading from the last run.  So that is why I had that little Do Until loop at the end for unloading.  Once I put that into place this was working perfectly for me.

 

Yeah, that's what I experienced too. I used a Do Until loop as well to repeat the unload attempt (fails and warns after five tries) until the HKU count matched the initial HKU count before loading the hives. Hopefully the DllCall method is more reliable, but like I said, haven't got that figured out yet.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0

  • Similar Content

    • Simpel
      By Simpel
      Hi,
      I wondered why negative integers I wrote into registry (e.g. negative x-coordinates of a gui if using two monitors and the right one is the main one) wouldn't return right when reading. Now I know: it is saved as an unsigned integer (without algebraic sign). So here is a snippet that is changing unsigned to signed integer:
      Global Const $g_sRegKey = "HKEY_CURRENT_USER\Software\" & @ScriptName ; path to registry RegWrite($g_sRegKey, "Value", "REG_DWORD", -2147483647) ; write some negative integer into registry; -2147483647 highest possible negative integer , 2147483648 highest possible positive integer if talking of 32bit Local $sValue = RegRead($g_sRegKey, "Value") ; read out registry ConsoleWrite("Value: " & $sValue & @CRLF) ; show real value in console Local $sResult = _SignedInteger($sValue) ; change to signed value ConsoleWrite("Result: " & $sResult & @CRLF) ; and show it in console Func _SignedInteger($iUnsignedInteger) Local $iSignedInteger If $iUnsignedInteger > (2^31) Then ; then it means a negative integer $iSignedInteger = $iUnsignedInteger - (2^32) Else $iSignedInteger = $iUnsignedInteger EndIf Return $iSignedInteger EndFunc It took me some time to find out the problem and so I hope I can help somebody with this.
      Regards, Conrad
    • GreenSparks
      By GreenSparks
      Hi!
      I post here because i was wonderring if someone in this forum could help me with my script.
      What i'm trying to do, is to basically install a new keyboard layout in Windows and activate it. I want to acheive by the registry or the command line, but not with the autoit automation tools, i don't find it stable...
      Thanks for your help and have a good day!
    • Leo1906
      By Leo1906
      Hello guys,
      I'm having a problem right here ..
      I was trying to create a few Registry Values using autoit, but it seems to me that Autoit can't write those values to this specific part of the registry ..
      Here is the code I'm trying to run:
      RegWrite("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\test\command", "", "REG_SZ", "C:\test\convert.exe %1 geojson|convert") I'm definitly sure that the path is correct. Script is runned with Admin Rights. Everything's fine here.
      It's possible to read other values stored by Windows in this directory:
      MsgBox(0, 0, RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\Windows.burn", "Description")) But you can't edit those using Autoit. I don't know what this is. In my eyes it's an Autoit Bug or something like that ...
      Possible solution for me is to write a ".reg" file and run it afterwards, but this is an unclean method I don't really want to use ..
      Any suggestions on this?
       
      Edit: the OS is Windows 7 x64 German Language btw ..
    • ur
      By ur
      I have a registry value in which the name is having \ and when I am trying to delete the registry,it is failing because of \.
      The registry is given below.
       
      Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Microsoft\Active Setup\Installed Components\{2D46B6DC-2207-486B-B523-A557E6D54B47}] "Version"="9,0,8112,16421" "Locale"="*" "C:\\ProgramData\\Symantec\\Symantec Endpoint Protection\\"="C:\\ProgramData\\Symantec\\Symantec Endpoint Protection\\" Can you please suggest how to delete the last value.
    • Wicked_Caty
      By Wicked_Caty
      I wanted to have a few lines that copy the whole registry into a file. I know that there is RegRead, but I don't want to type every single key into my code...
      Any way of doing this easily? Filetype doesn't matter, as long as it isn't encrypted. A batch or exe would be okay, if it's in the same location on every PC. Doing this without admin permissions would be awesome too
      Thanks