12
votes

I have some program settings that are currently stored in HKEY_LOCAL_MACHINE. Due to Vista and locked down users, some users don't have permission to HKEY_LOCAL_MACHINE, and those values don't really belong to HKEY_LOCAL_USER either (it has to be the same for all users), what's the best alternative location for storing these?

Majority of settings are stored in the DB already, but there are some that the program needs to know about before connecting to the DB. Ideally I'll like a way to implement this without needing to check what operating system is running.

This is for a desktop app written in Delphi.

10
This is going to be one good thing to come from Vista, even if not much else good does. We'll end up with much cleaner registries after all this junk is finally excised.Joel Coehoorn
Are you sure they don't have read permissions? A standard user on XP does not have read write permissions to HKLM either.Jamie
Guess I could have clarified it more. They're settings where the user will write to the registry as well.Robo
How would your application behave under Windows 2000 or Windows XP as a standard user? That will guide you how it should behave under Windows Vista or Windows 7 as a standard user.Ian Boyd

10 Answers

33
votes

You should put:

  • personal settings (like window position and minor preferences) under HKEY_CURRENT_USER in the registry or in the CSIDL_APPDATA or CSIDL_LOCAL_APPDATA folder;
  • important application settings (like a fixed path that should not be modified by your users) under HKEY_LOCAL_MACHINE in the registry or in the application's folder. Set them at install time, when administrator privileges are available;
  • shared data (data that all of your users should read and write to, like a simple database) in the CSIDL_COMMON_APPDATA folder.

Use SHGetFolderPath to find the location of the CSIDL_* folders.

Depending on your needs you might like to implement all three options given at once. There would be nothing wrong with it.

13
votes

Might be some good place in the registry to put them I don't know about, but why not just add an ini-file in C:\Documents and Settings\All Users\Application Data\yourApp

2
votes

What @uli said, with one exception.

Settings that never change or should only be changed by an administrator can --should, even-- be kept in the same folder as the application to help prevent tampering.

Connection info for a database sounds like the kind of thing that shouldn't be changed without administrator intervention. Therefore in this case your application's folder might be okay.

1
votes

You mentioned HKEY_LOCAL_USER, but I don't see that in the top-level in the Registry. I am guessing you must mean HKEY_CURRENT_USER.

I put my user settings under HKEY_CURRENT_USER/Software/my-program. I find that this works under Vista without problem.

But since you say you have settings that apply to all users that you don't want under HKEY_CURRENT_USER, then you might try either:

HKEY_USERS/.DEFAULT/Software/your-program

or

HKEY_CURRENT_CONFIG/Software/your-program

I'm afraid I don't use either of those locations so I can't tell you if they work on Vista or not, but I do see that some software vendors have added registry entries there.

1
votes

Save stuff in %APPDATA% or %LOCALAPPDATA%

1
votes

Ask yourself if your setting really is for all users. Is it really for all users?

Carefully think about this question:

How did the software run under Windows XP as standard user?

  • Did the software simply crash?
  • Was configuring the option disabled?
  • Did you tell your customers that they had to run as an administrator, and if they refused then you wouldn't support it?

Because if your software absoutely requires you to be an administrator, then simply add the manifest to the executable saying it needs to be run as an administrator:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
   <assemblyIdentity 
      version="1.0.0.0"
      processorArchitecture="X86"
      name="IsUserAdmin"
      type="win32"/> 

   <description>Description of your application</description> 

   <!-- Identify the application security requirements. -->
   <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
      <security>
         <requestedPrivileges>
                <requestedExecutionLevel
               level="requireAdministrator"
               uiAccess="false"/>
         </requestedPrivileges>
      </security>
   </trustInfo>
</assembly>

And presto, you're an administrator.


But i don't think you really need to be an administrator. The only time you need a local machine setting is if you're going to have users from multiple logins or sessions using the software. If it really is something that applies to every user, shouldn't the installation program have set it up?

We had the same question come up here. A surveillance system needs to configure which capture device will be used by the software. You could say that all surveillance operators will be using the same capture device, so once one picks it, that setting is global to all operators. But that's just not true in practice. Chances are there's only once capture device, and it's the one we use. If there's more than one, then the user can simply pick another device.


But there are a few ways to handle this

i) Have the settings saved in the registry, and have the installation program set the ACL on the key give all users Full Control.

ii) Have the settings saved in the

%APPDATA%\Surveillance\settings.ini

file. Have the installation program create the settings file, and ACL it to allow all users to have Full Control

iii) Store the settings in a the above mentioned registry key or ini file, and use

to add the UAC Shield to your Save/OK/Apply button. When the user pushes the button, you relaunch your app elevated (using RunAsAdmin), passing command line parameters indicating what you want to change.

iv) Do the same as 3, but do it before they can get into the screen that is used to edit the values.

v) Do the same as 4, but have the values initially read only, and if they want change them they have to elevate.

vi) Have the options disabled if the user is running as a standard user, and if they want to change them: right-click the executable and select

Run as administrator


If this is an option that a user was able to change whenever they liked (when you were running on Windows XP and the user was an administrator), then it seems that user's being able to edit the value at will is acceptable.

In this case you can just let the user type in the name of the server, as they were allowed to do before. If the user has permission to write to HKLM, then save the option there. Otherwise save it in HKCU. When reading which server to use, start with HKCU and move to HKLM if HKCU value is not there.

1
votes

Re using ini files - beware that there seems to be a 2048 byte limit on items.

I've come unstuck because of this - encoded licence info hovering around the (then unknown) limit & something that always seemed to work breaking 'mysteriously' when they go over...

0
votes

Can you make a .msi file that can be used to push the registry settings out through group policy?

0
votes

There's always old fashioned INI files. They are more portable that registry settings. Another option would be an XML file.

Don't store them in the Program Files directory though - Vista won't like that.

0
votes

I read all the answers here and stuff elsewhere and the answer seems to be... Don't use the registry! Is this really what Microsoft wants us to do with program config data that applies to all users!?