Jump to content

Directing Reg changes to the user, not the admin that ran the exe


Recommended Posts

I am making a AutoIT to install a program and make all the nessicary registry changes that need to be done with it. The problem is all these changes are in HKEY_CURRENT_USER, so when I run this exe as admin for a user, it makes all the registry changes in the Admin's account who ran it.

Is there a way to direct these reg changes to the logged in user's account? Or make them happen to all current and future accounts on the computer?

Link to comment
Share on other sites

What is in your script that requires you to run it as an Admin? Because, if HKCU is the only location you're writing to you don't need to be an admin to do it.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

What is in your script that requires you to run it as an Admin? Because, if HKCU is the only location you're writing to you don't need to be an admin to do it.

 

It is also installing software program a long with the registry settings.

Link to comment
Share on other sites

  • Moderators

Rather than trying to hack away at the registry, I would look into using Active Setup. Basically you create an HKLM key which is compared on each login. If that key does not exist in HKCU, it is copied over. You can even set this up to run an executable or other script, if you have a large number of files that need to be copied over.

As an example:

  • I have a computer with 3 users - Joe, Bob, and Jeff.
  • I run an install as the SYSTEM or Administrator account, but it does not enter registry settings for the currently logged in user.
  • I create the following key - HKLMSOFTWAREMicrosoftActive SetupInstalled Components{CB3F7EDD-9D0F-43C1-90FC-4F53EAE172A1}
    • Note the key must be unique - typically a GUID
  • Under the new key, I create my registry entries (Version, Name, License, etc.).
  • I can also create a REG_SZ called StubPath and point it to a script or external executable.
  • When a user logs into the system, the Active Setup hive in HKLM is compared with the one in HKCU. If there is a key missing, it is processed - entries are moved over and scripts are run.
  • The next time the user logs in, the keys match, so no action is taken.

"Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball

How to get your question answered on this forum!

Link to comment
Share on other sites

If the user's registry hive is loaded their SID will be loading into the HKEY_USERS hive.  I have a vbs script I use to mount all profile registry hives in this manner, but never took the time to convert it to AU3 (which shouldn't be very difficult).  I'll be happy to share it if you are interested.

Link to comment
Share on other sites

  • Moderators

If the user's registry hive is loaded their SID will be loading into the HKEY_USERS hive.  I have a vbs script I use to mount all profile registry hives in this manner, but never took the time to convert it to AU3 (which shouldn't be very difficult).  I'll be happy to share it if you are interested.

 

Yes there are a number of ways you can do it in VBScript. I have the same issue; have about 10 of them and have never bothered with converting. This is the one I use most often.

http://micksmix.wordpress.com/2012/01/13/update-a-registry-key-for-all-users-on-a-system/

"Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball

How to get your question answered on this forum!

Link to comment
Share on other sites

Here's mine.

'---------Global Variables---------

    varTime = Time
    Const HKEY_LOCAL_MACHINE = &H80000002
    Const HKEY_USERS = &H80000003
    strComputer = "."
    DQ = Chr(34)

'----------------------------------


'---------Script Execution---------

    UserSIDs = Split(GetSIDs,",")

'    for each objSID in UserSIDs
'   WriteRegFile(objSID)    
'    next

    wscript.echo "Complete.  Duration: " & Duration(varTime)
    wscript.quit

'----------------------------------


'-------Sub & Function Code--------

'Gather All Account SIDs on local machine
    Function GetSIDs
    Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv")
    strKeyPath = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
    oReg.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrSubKeys
 
    For Each subkey In arrSubKeys
        results = results & subkey & ","
    Next

    Result = FilterSIDs(results)
    GetSIDs  = Result
    End Function


'Filter only Established Profiles
    Function FilterSIDs(SID)
    arrResults = Split(SID,",")

    For i = 0 to UBound(arrResults)
        if Len(arrResults(i)) > 10 then 
        Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv") 
        strKeyPath = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\" & arrResults(i)
        strValueName = "ProfileImagePath"
        oReg.GetExpandedStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strValue
        'if Instr(1,strValue,"Admin") < 1 and Instr(1,strValue,"what") < 1 then
            set objFS = CreateObject("Scripting.FileSystemObject")
            Rslt = objFS.FolderExists(strValue)
            if Rslt = True then 
            varSIDs = varSIDS & arrResults(i) & ","
            MountResult = MountNTUser(strValue,arrResults(i))
            wscript.echo "------------------------------------------------------------"
            wscript.echo arrResults(i) & vbcrlf & strValue & vbcrlf & MountResult
            wscript.echo "------------------------------------------------------------" & vbcrlf
            end if
        'end if
        end if
    Next

    if right(varSIDs,1) = "," then varSIDs = left(varSIDs,Len(varSIDs) - 1)
    FilterSIDs = varSIDs
    End Function


'Mount NTUser.dat file(s)
    Function MountNTUser(path,SID)
    Set WshShell = CreateObject("WScript.Shell")
    Set Exec = WshShell.Exec("%windir%\system32\reg load HKU\" & SID & " " & chr(34) & path & "\ntuser.dat" & chr(34))  
    strOutput = Exec.StdOut.ReadAll
    if instr(1,strOutput,"success") > 1 then
        MountNTUser = "Successful!"
    else
        MountNTUser = "Warning! Failed to Load Hive!"
    end if
   End Function


'Execution Duration Check
    Function Duration(varTime)
    varTime = Left(varTime,Len(varTime) - 3)
    arrStartTime = Split(varTime,":")
    varTime = Time
    varTime = Left(varTime,Len(varTime) - 3)
    arrEndTime = Split(varTime,":")
    if arrEndTime(1) > arrStartTime(1) then
        Duration = ((arrEndTime(1) - arrStartTime(1)) * 60 + arrEndTime(2)) - arrStartTime(2) & " second(s)."
    else
        Duration = arrEndTime(2) - arrStartTime(2) & " second(s)."
    end if
    End Function
'----------------------------------

edit:

There is some erroneous code in there too (like the duration func and the logging) which is not required if the intent is to convert it to AutoIt.
In fact, There are REG funcs that would eliminate the need for WMI if executed on a local box.
 

Does AutoIt not already have bult-in functions or a UDF for this purpose already?

I'm not aware of such a UDF.

Edited by spudw2k
Link to comment
Share on other sites

JLogan3o13 & spudw2k,

Thank you both for sharing your VBScript code with me. I'm really surprised that this has not yet been brought into the AutoIt fold, as it is a very useful functionality! Since I will be working on replacing my VBScript scripts with AutoIt, I plan to bring this into AutoIt (and I agree with you spudw2k, I like to stay away from WMI if at all possible since I cannot rely on it working on every PC). If I do so, I will certainly share here with the rest of the AutoIt community.  :D

Link to comment
Share on other sites

I'm motivated to do so as well with the spin up of this topic.  I'll post what I get when I'm done.
Any desired features?  Here's my initial UDF Desc. Outline

; #FUNCTION# ====================================================================================================================
; Name...........: _MountUserProfileRegHives
; Description ...: Loads User Profile NTUSER.DAT Files into their respective HKEY_USERS SID Hives
; Syntax.........: _MountUserProfileRegHives( [ $Verbose, $Filter, $Mode ] )
; Parameters ....: $Verbose - [optional] Provides Verbose Information via SetExtended
;                  $Filter - [optional] Specify User Profile(s)
;                  $Mode - [optional] Filter Operation Mode
;                  |0 = Omit Specified User Profile(s)
;                  |1 = Include Specified Profiles(s)
; Return values .: Success - Returns 1
;                          - @extended contains verbose output if $Verbose = True
;                  Failure - Returns 0 and Sets @error:
;                          |0 - Failed to load User Registry Hive(s)
;                             - @extended contains specifc failures
;                          |1 - Invalid $Verbose
;                          |2 - Invalid $Filter
;                          |3 - Invalid $Mode
; Author ........: Spudw2k
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: 
; ===============================================================================================================================

edit:  Never used SetExtended before, turns out only Integers can be returned.  Will prob just use strings but not sure the "proper" way to document that in the UDF Standard desc.

Edited by spudw2k
Link to comment
Share on other sites

That's great, spudw2k! Well, the main feature that comes to mind is the capability to omit certain profiles (LOCAL SERVICE,NETWORK SERVICE,SYSTEM, etc.) and whether or not to include the .DEFAULT profile (won't always want to include it), but it looks like you're going to be including that feature. Of course, we'll want to be able to load/mount and unload/unmount and be able to add, edit and delete all (or as many as possible) of the different reg types.

The VBScript reference that JLogan3o13 provided looks like a good source/template: http://micksmix.wordpress.com/2012/01/13/update-a-registry-key-for-all-users-on-a-system/

Link to comment
Share on other sites

Sounds good to me.  I'm fairly crunched for time, but I'll workon this as I can.  Here's where I'm at so far (far from complete).

#include <Array.au3>   ;Testing purposes only

_MountUserProfileTempRegHives()

; #FUNCTION# ====================================================================================================================
; Name...........: _MountUserProfileTempRegHives
; Description ...: Loads User Profile NTUSER.DAT Files into HKU\Temp Hive by SID
; Syntax.........: _MountUserProfileTempRegHives( [ $Verbose, $Filter, $Mode ] )
; Parameters ....: $Verbose - [optional] Provides Verbose Information via SetExtended
;                  $Filter - [optional] Specify User Profile Directories(s)
;                  $Mode - [optional] Filter Operation Mode
;                        |0 = Omit Specified User Profile(s)
;                        |1 = Include Specified Profiles(s)
; Return values .: Success - Returns 1
;                          - Returns String containing verbose output if $Verbose = True
;                  Failure - Returns 0 and Sets @error:
;                          |0 - Failed to load User Registry Hive(s)
;                             - Returns String containing verbose output if $Verbose = True
;                          |1 - Invalid $Verbose
;                          |2 - Invalid $Filter
;                          |3 - Invalid $Mode
; Author ........: Spudw2k
; Modified.......:
; Remarks .......:
; Related .......: _GetProfileList
; Link ..........:
; Example .......:
; ===============================================================================================================================

;incomplete
Func _MountUserProfileTempRegHives($Verbose = False, $Filter = "", $Mode = 0)
    If Not IsBool($Verbose) Then Return SetError(1, 0, 0)
    If Not IsString($Filter) And Not UBound($Filter) Then Return SetError(2, 0, 0)
    If Not ($Mode <> 0 Or $Mode <> 1) Then Return SetError(3, 0, 0)
    Local $arrProfileList = _GetProfileList()
    _ArrayDisplay($arrProfileList)
EndFunc   ;==>_MountUserProfileTempRegHives

; #FUNCTION# ====================================================================================================================
; Name...........: _GetProfileList
; Description ...: Retrieves ProfileList Subkeys from Registry
; Syntax.........: _GetProfileList
; Parameters ....:
; Return values .: Success - Returns Two-Dimension Array with Profile SIDS and Profile Paths
;                  Failure - Returns 0 and Sets @error:
;                          |1 - Unable to Enumerate ProfileList Key
; Author ........: Spudw2k
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......:
; ===============================================================================================================================

Func _GetProfileList()
    Local $arrProfileList[1][2] = [["SID", "ProfileDir"]]
    Local $regKeyRoot = "HKLM\Software\Microsoft\Windows NT\CurrentVersion\ProfileList"
    Local $idx = 1
    While 1
        $regProfileSID = RegEnumKey($regKeyRoot, $idx)
        Switch @error
            Case 1
                Return SetError(1, 0, 0)
            Case -1
                ExitLoop
        EndSwitch
        If Not (StringLen($regProfileSID) <= 8) Then
            $regProfileDir = RegRead($regKeyRoot & "\" & $regProfileSID, "ProfileImagePath")
            If Not @error Then
                $arrUbound = UBound($arrProfileList)
                ReDim $arrProfileList[$arrUbound + 1][2]
                $arrProfileList[$arrUbound][0] = $regProfileSID
                $arrProfileList[$arrUbound][1] = $regProfileDir
            EndIf
        EndIf
        $idx += 1
    WEnd
    Return $arrProfileList
EndFunc   ;==>_GetProfileList

; #FUNCTION# ====================================================================================================================
; Name...........: __RunRegLoadUnloadCMD
; Description ...: Executes context sensitive REG LOAD/UNLOAD Command
; Syntax.........: __RunRegLoadUnloadCMD( $Mode, $HivePath, [ $RegFile ] )
; Parameters ....: $Mode - Mode of Operation
;                        |0 = Unload
;                        |1 = Load
;                  $HivePath - Path to the Hive Key (HKU\TempHive\SID)
;                  $RegFile - [optional] Required RegFile for Load Operation only.  Ignore if Unload
; Return values .: Success - Returns 1
;                  Failure - Returns 0 and Sets @error:
;                          |0 - Reg Command Failed
;                          |1 - Invalid $Mode
;                          |2 - $RegFile does not exist
; Author ........: Spudw2k
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......:
; ===============================================================================================================================

Func __RunRegLoadUnloadCMD($Mode, $HivePath, $RegFile = "")
    If Not ($Mode <> 0 Or $Mode <> 1) Then Return SetError(1, 0, 0)
    If Not FileExists($RegFile) Then Return SetError(2,0,0)
    Local $regCMD = @SystemDir & "\REG.EXE "
    Switch $Mode
        Case 1
            $regCMD &= "LOAD " & $HivePath & " " & $RegFile
        Case 0
            $regCMD &= "UNLOAD " & $HivePath
    EndSwitch
    ;Local $pid = Run($regCMD,@ScriptDir,@SW_HIDE,$STDERR_MERGED)
    ;Local $line
    ;While 1
    ;    $line &= StdoutRead($pid)
    ;    If @error Then ExitLoop
    ;WEnd
EndFunc

I intend to create functions to write to user profiles which will allow the inclusion or ommision of "system accounts", as well as supporting functions (unmount temp userprofile hives, etc.)  This is a fun exercise for me as I need to work on better documentation for my scripts.

edit: added automatic filter to _GetProfileList() to omit Local Service account SIDs.  Those hives are already loaded into HKU at runtime.  Will still provide capability to wrtie to those hives as well as .Default but will omit by default.

Edited by spudw2k
Link to comment
Share on other sites

Sorry, haven't had much time to work on this.  Had some major outage issues at work this weekend, but at least I'm almost at my 40 for the week (not that I'll get off early.) ;)  I just wanted to reach out to say I haven't forgot about this.

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...