[sword-devel] BibleCS Installer: HKCU vs HKLM

DM Smith dmsmith555 at yahoo.com
Mon Feb 13 10:22:44 MST 2006

L.Allan-pbio wrote:
> Regarding use of HKCU vs HKLM (split from general Installer thread to 
> be focused on this issue alone) :
> Here is some sample code for a custom page allowing choice of "Just 
> this user" and "All Users". It is pretty stripped down just to 
> illustrate the basics of how it works.
I played with this code and it works as advertised.
However, in trying to get it to work, I ran into lots of other 

Basically different scenarios that could happen on a machine raised 
questions on what should happen:
1) Reinstall (i.e. user runs install a second time without uninstalling 
first) and instead of choosing HKCU, which was the install, now chooses HKLM
2) The user only has limited install privs and chooses HKLM.
3) The user tries to install 1.5.8 as HKCU, but the application has 
already been installed as HKLM.
4) User upgrades (e.g. to > 1.5.6) from a prior HKCU (e.g. <= 1.5.6) and 
    a) HKCU, or
    b) HKLM
5) User upgrades (e.g. to > 1.5.8) from a prior HKLM (e.g. 1.5.8) and 
    a) HKCU, or
    b) HKLM

I am sure there are others.

The other question I had was what should happen for a limited user install?
Can the user install to C:\Program Files?
The application writes to the installation dir for user prefs, install 
sites, modules and the like. Will this work for a limited user?

If the application is installed to a shared workstation by an 
administrator and the first administrator runs the program and changes 
the layout to what they like, won't that be the layout that the next 
administrator sees?

I also ran into a problem trying to establish $INSTDIR.
The way it should work is that the installer sets a default.
Then it looks for a prior HKLM installation and if it is present, then 
the default is set to that.
Then it looks for a prior HKCU installation and if it is present, then 
the default is set to that.
And it should note whether HKLM or HKCU was used to for the default and 
use that as the default root when presenting to the user.
This is so that SetShellVarContext can be called appropriately (all for 
hklm and current for hkcu).

NSIS provides the following commands to help:
To establish the default:
InstallDir default\dir\path
To reset the default to the prior installation, if found:
InstallDirRegKey ROOT subkey keyname

However, these cannot be in a section or in a function.
And InstallDirRegKey does not take SHCTX, forcing using either HKCU or 
HKLM (or any other explicit root).
I tried calling InstallDirRegKey twice once with HKLM and once with 
HKCU, but the second call is ignored upon compilation.
The further problem is that even if it could be called twice, the value 
of $INSTDIR cannot be examined at each point to determine which root to 
use, as StrCmp and StrCpy cannot be used outside of functions and sections.

What this would leave is not using InstallDir and InstallDirRegKey, but 
in the function .onInit, simulate this behavior and establish INSTDIR 
via StrCpy
and then call SetShellVarContext to set the default.

The other gotcha is that under section D.2 of the NSIS manual it clearly 
states that HKCU is available to Add/Remove Programs for NT4/2000/XP and 
that HKLM needs to be used for earlier systems.

Even though the HKCU may exist prior to these, it probably should not be 
used at all. So this would mean adding conditional logic into whether 
the page is shown or not.

Anyway, I think this is a big hurdle and is better left to a later date. 
I think for now we should assume that the user is an administrator and 
that all users share the one configuration.

> (I haven't tested with a "limited user" account to see what happens. I 
> suppose that could be detected with Contrib\UserInfo\UserInfo.nsi  and 
> only allow "current" and don't even show the custom page ...  my 
> impression is that a "limited user" can still read HKLM)
> ;*************** ini file ************
> # HkcuVsHklm_CustomPage.ini
> [Settings]
> NumFields=2
> [Field 1]
> Type=RadioButton
> Text=Install for just this user
> State=1
> Left=0
> Right=-10
> Top=0
> Bottom=12
> [Field 2]
> Type=RadioButton
> Text=Install for all users on this computer
> State=0
> Left=0
> Right=-10
> Top=20
> Bottom=32
> ********** Installer ***************
> !include Sections.nsh
> !include "MUI.nsh"
> Var HkeyChoice
> Page custom PreShowInstallChoices LeaveInstallChoices ": Just this 
> user or all users"
> !insertmacro MUI_PAGE_INSTFILES
> !insertmacro MUI_LANGUAGE English
> ;--------------------------------
> ; Installer attributes
> Name "Modern UI Test"
> OutFile HkcuVsHklm.exe
> InstallDir "$PROGRAMFILES\Modern UI Test"
> InstallDirRegKey HKCU "Software\Modern UI Test" ""
> LangString TEXT_IO_TITLE ${LANG_ENGLISH} "CrossWire family of 
> applications."
> LangString TEXT_IO_SUBTITLE ${LANG_ENGLISH} "Explanation about 
> choosing 'Just this User' vs 'All Users' goes here."
> Function .onInit
>  DeleteRegValue HKLM "SOFTWARE\CrossWire\The SWORD Project" "HkcuVsHklm"
>  DeleteRegValue HKCU "SOFTWARE\CrossWire\The SWORD Project" "HkcuVsHklm"
>  StrCpy $HkeyChoice "current"
>  !insertmacro MUI_INSTALLOPTIONS_EXTRACT "HkcuVsHklm_CustomPage.ini"
> FunctionEnd
> # Installer sections
> Section -Main WriteFiles
> SectionEnd
> Section -post WriteRegistryEntries
>  WriteRegStr SHCTX "SOFTWARE\CrossWire\The SWORD Project" "HkcuVsHklm" 
> "$HkeyChoice"
> SectionEnd
> Function PreShowInstallChoices
>  !insertmacro MUI_INSTALLOPTIONS_DISPLAY "HkcuVsHklm_CustomPage.ini"
> FunctionEnd
> Function LeaveInstallChoices
>  ; At this point the user has either pressed the Next Button or one of 
> our custom RadioButtons
>  ; We find out which by reading the "Settings" field from the INI file
>  !insertmacro MUI_INSTALLOPTIONS_READ $0 "HkcuVsHklm_CustomPage.ini" 
> "Settings" "State"
>  StrCmp $0 0  NextButtonPicked
>  StrCmp $0 1  JustThisUser
>  StrCmp $0 2  AllUsers
>  Abort ; Return to the page to allow further choices
> JustThisUser:
>  StrCpy $HkeyChoice "current"
>  Abort ; Return to the page
> AllUsers:
>  StrCpy $HkeyChoice "all"
>  Abort ; Return to the page
> NextButtonPicked:
>  StrCmp $HkeyChoice "current" 0 UseAll
>    SetShellVarContext current
>    GoTo ChoiceDone
>    UseAll:
>    SetShellVarContext all
>  ChoiceDone:
> FunctionEnd
> Function .onInstSuccess
>  ReadRegStr $0 SHCTX "SOFTWARE\CrossWire\The SWORD Project" "HkcuVsHklm"
>  MessageBox MB_OK "Hkey Choice: $0"
> FunctionEnd
> _______________________________________________
> sword-devel mailing list: sword-devel at crosswire.org
> http://www.crosswire.org/mailman/listinfo/sword-devel
> Instructions to unsubscribe/change your settings at above page

More information about the sword-devel mailing list