DennisFeiock
30th March 2005 14:25 UTC
HKCU on multiple user systems
I was hoping to get some help with a problem I am running into. I have tried doing a search, but havent come up with much... I could just not be searching quite the way I should be. Regardless, here is what I am doing:
I am automating installs of applications. Naturally, most of these installs write registry entries to the HKCU. The problem I am having is writing the required HKCU keys for a second user logging into the system.
I attempted just making the required changes to HKEY_USERS for each user on the system (manually), but it doesnt load the changes into the HKCU when the user logs in.
As far as I see it, there is two ways to make the necessary changes:
1) With the install, write all the necessary HKCU entries to the HKEY_USERS, for each user. Then force windows to load the changes when the users log in.
2) Write a HKLM key (Installed.Apps) and a HKCU key (Configured.Apps). Upon the user logging in, compare Installed.Apps to Configured.Apps, and run the secondary installs (which would contain just HKCU entries) if an application has not been configured for that user yet.
Now, for each of these options I would still need assistance with the following things:
Situation 1) I'm not sure if there is a command to load the user's registry entries from the HKEY_USERS keys to HKCU (such as "System::Call 'Shell32::SHChangeNotify(i ${SHCNE_ASSOCCHANGED}, i ${SHCNF_IDLIST}, i 0, i 0)'" for loading changes to file associations). Each system has users that has logged into the system already. I would need to read out each user under HKEY_USERS (eg: S-1-5-18, S-1-5-19, etc) in order to make the changes to all the users correctly. Then, of course, I would have to make the changes to the Default user as well.
Situation 2) Not all the systems have the same installed applications. When using ReadRegStr, you have to define the Name of what entry you want to read. I would have to append the names to the default key, then parse them out to be able to compare.
Those are the two scenarios that I could think of that would resolve this problem I am having. There could be others, and I would be more than happy to hear them. Any help would be greatly appreciated. :D
Thanks!
Dennis Feiock
kichik
31st March 2005 19:37 UTC
You can try the following solution from the Archive:
http://nsis.sourceforge.net/archive/...php?pageid=511
DennisFeiock
1st April 2005 12:39 UTC
Thanks for the input kichik.
The only problem with the solution provided there is that it only pertains to that single application.
What I am attempting to do is make any HKCU registry changes for a user silently when logging in. So it will have to detect which applications are installed on the system, and which have been configured for the user.
I almost got it done yesterday by writing a reg key to HKLM and HKCU specifing which apps are installed, and which are configured for the current user. Then parsing out those entries and running the secondary (HKCU entries only) installs if needed.
The problem I ran into doing it that way was if there were a version upgrade with new registry entires required, and removing the value for apps that have been uninstalled. The cause of the problem was that I was just using the default key and dumping like so:
"app1;app2;app3;"
And after 100 lines of script (wich spacious formatting) with 4 loops, I figured enough was enough. :(
After rethinking the situatuion, there are really only about 20 different installers that I might create. So, using the array header found here (Thanks Afrow UK!):
http://forums.winamp.com/showthread....ighlight=array
I am rebuilding the app and will just make an array with the registry keys that need to be checked. I really think this one should take care of it for me. Or I hope at least. Will let you know how it goes. :D
- DF
kichik
1st April 2005 12:47 UTC
The application list doesn't have to be in one value. You can create a key and add several values to it. Use EnumRegKey to find out which applications need to be configured. It will save you the string hassling.
DennisFeiock
1st April 2005 12:52 UTC
I figured there had to be a way to do that, I just didnt know the command and didnt know where to look to find it.
Thanks a ton! :D
- DF
DennisFeiock
1st April 2005 19:39 UTC
WORKIING!
Well! I finally got things working the way that I wanted them to. Just thought I would post my results here for anyone that might be doing a search that has a similar problem.
Now, I will be the first to admit that I am pretty new to NSIS. Maybe 2 weeks or so... So Im sure theres a way to clean up this code and make it more efficent... but here goes...
::ASSUMPTIONS:
1. All install exe's are located on a network share
2. Registry keys are created to point to the location for different installs
::HKLM REGISTRY EXAMPLE::
Lets say I created an install called "App1" and it is shared at "\\server\share\App1.exe"
With App1, you would need to create a registry structure such as:
HKLM\Software\Custom.Apps\Installed.Apps\App1
"Default" "" (Not used)
"CUInstall" "[Path to CU install]" (secondary install with just HKCU and shortcut entries)
"Install" "[Path to install]" (path to full install exe)
"Version" "[#]" (Version number of the application)
So, in this case, there would be the following Names and Values:
"CUInstall" "\\server\share\App1-CU.exe"
"Install" "\\server\share\App1.exe" (Not used by my script, just thought it would be a good idea)
"Version" "1.0"
::APP1-CU::
This would be a compiled exe with only Registry entries and user-specific shortcuts. I ended up completely removing these options from the full install, then calling the system to run the RegCheck application to inject the necessary files/entries after the full install is completed.
::HKCU REGISTRY EXAMPLE::
With the App1-CU, you would need to add the following registry entries to compare what was installed on the local system.
HKCU\Software\Custom.Apps\Configured.Apps\App1
"Default" "" (Not Used)
"un.CUInstall" "[Path to install]" (uninstall if needed)
"Version" "[#]" (Version number of the application)
::CODE::
OutFile RegCheck.exe
Name RegCheck
Caption RegCheck
Section
Push $R0 #Counter
Push $R1 #EnumValue
Push $R2 #HKLMversion
Push $R3 #HKCUversion
Push $R4 #CUInstallPath
Push $R5 #un.CUInstallPath
StrCpy $R0 0
HKLMloop:
EnumRegKey $R1 HKLM Software\Custom.Apps\Installed.Apps\ $R0
StrCmp $R1 "" +5
DetailPrint "HKLM Install found: $R1"
Call HKLMCheck
IntOp $R0 $R0 + 1
goto HKLMloop
StrCpy $R0 0
HKCUloop:
EnumRegKey $R1 HKCU Software\Custom.Apps\Configured.Apps\ $R0
StrCmp $R1 "" +5
DetailPrint "HKCU Install found: $R1"
Call HKCUCheck
IntOp $R0 $R0 + 1
goto HKCUloop
Pop $R0
Pop $R1
Pop $R2
Pop $R3
Pop $R4
Pop $R5
SectionEnd
Function HKLMCheck
ReadRegStr $R2 HKLM Software\Custom.Apps\Installed.Apps\$R1 "Version"
ReadRegStr $R3 HKCU Software\Custom.Apps\Configured.Apps\$R1 "Version"
StrCmp $R2 $R3 +4 0
ReadRegStr $R4 HKLM Software\Custom.Apps\Installed.Apps\$R1 "CUInstall"
ExecWait '"$R4" /S'
DetailPrint "Installing HKCU entries for: $R1"
DetailPrint "Check OK."
FunctionEnd
Function HKCUCheck
ReadRegStr $R2 HKLM Software\Custom.Apps\Installed.Apps\$R1 "Version"
ReadRegStr $R3 HKCU Software\Custom.Apps\Configured.Apps\$R1 "Version"
StrCmp $R3 $R2 +5 0
ReadRegStr $R5 HKCU Software\Custom.Apps\Configured.Apps\$R1 "un.CUInstall"
ExecWait '"$R5" /S'
IntOp $R0 $R0 - 1
DetailPrint "HKCU entry with no HKLM setup, running uninstall for: $R1"
DetailPrint "Check OK."
FunctionEnd
::END OF CODE::
The one thing that I really wanted to do with this, but could not get it to work would to only have one loop rather than a HKLM and HKCU loop. Unfortunatly, I had some problems with the EnumRegKey running completely off of variables. And even when I hardcoded those in, I still could not get the Call command to work with a variable.
As far as implementing the RegCheck application, I created an install that would create a batch file which would eventually run RegCheck.exe from the server each time a user would log in. I had to do it that way because there were some problems where the network interface would not act right unless I tried to do an "ipconfig /renew" first. Even though the command would timeout. Was pretty strange...
So, as a final result, this application runs when each user logs into the system. It runs silently, and calls any needed user configuration installs silently. For my purposes, this makes it so that each user doesnt have to go in and define querys/servers/etc. for certain applications. Then again, Im sure some of the application bundles I am makinig might not work so well without the HKCU entries.
Anyways! Thanks for all the help with EnumRegKey kichik :D
- DF