When - and why - should you store data in the Windows Registry? - windows

As a developer, tools that store configuration/options in the registry are the bane of my life. I can't easily track changes to those options, can't easily port them from machine to machine, and it all makes me really yearn for the good old days of .INI files...
When writing my own applications, what - if anything - should I choose to put in the registry rather than in old-fashioned configuration files, and why?

Originally (WIN3) configuration was stored in the WIN.INI file in the windows directory.
Problem: WIN.INI grew too big.
Solution (Win31): individual INI files in the same directory as the program.
Problem: That program may be installed on a network and shared by many people.
Solution(Win311): individual INI files in the user's Window directory.
Problem: Many people may share a windows folder, and it should be read-only anyway.
Solution (Win95): Registry with separate sections for each user.
Problem: Registry grew too big.
Solution (WinXP): Large blocks of individual data moved to user's own Application Data folder.
Problem: Good for large amounts of data, but rather complex for small amounts.
Solution (.NET): small amounts of fixed, read-only data stored in .config (Xml) files in same folder as application, with API to read it. (Read/write or user specific data stays in registry)

Coming at this both from a user perspective and a programmers perspective I would have to say there really isn't a good exceuse to put something in the registry unless it is something like file associations, or machine specific settings.
I come from the school of thought that says that a program should be runnable from wherever it is installed, that the installation should be completely movable within a machine, or even to another machine and not affect the running of it.
Any configurable options, or required dlls etc, if they are not shared should reside in a subdirectory of the installation directory, so that the whole installation is easily moved.
I use a lot of smaller utility like programs, so if it cant be installed on a usb stick and plugged into another machine and just run, then its not for me.

When - You are forced to due to legacy integration or because your customer's sysadmin says "it shall be so" or because you're developing in an older language that makes it more difficult to use XML.
Why - Primarily because the registry is not as portable as copying a config file that is sitting next to the application (and is called almost the same).
If you're using .Net2+ you've got App.Config and User.Config files and you don't need to register DLL's in the registry so stay away from it.
Config files have their own issues (see below), but these can be coded around and you can alter your architecture.
Problem: Applications needed configurable settings.
Solution: Store settings in a file (WIN.INI) in the Windows folder - use section headings to group data (Win3.0).
Problem: WIN.INI file grew too big (and got messy).
Solution: Store settings in INI files in the same folder as the application (Win3.1).
Problem: Need user-specific settings.
Solution: Store user-settings in user-specific INI files in the user's Window directory (Win3.11) or user-specific sections in the application INI file.
Problem: Security - some application settings need to be read-only.
Solution: Registry with security as well as user-specific and machine-wide sections (Win95).
Problem: Registry grew too big.
Solution: User-specific registry moved to user.dat in the user's own "Application Data" folder and only loaded at login (WinNT).
Problem: In large corporate environments you log onto multiple machines and have to set EACH ONE up.
Solution: Differentiate between local (Local Settings) and roaming (Application Data) profiles (WinXP).
Problem: Cannot xcopy deploy or move applications like the rest of .Net.
Solution: APP.CONFIG XML file in same folder as application - , easy to read, easy to manipluate, easy to move, can track if changed (.Net1).
Problem: Still need to store user-specific data in a similar (i.e. xcopy deploy) manner.
Solution: USER.CONFIG XML file in user's local or roaming folder and strongly-typed (.Net2).
Problem: CONFIG files are case-sensitive (not intuitive to humans), require very specific open/close "tags", connection strings cannot be set at run-time, setup projects cannot write settings (as easily as registry), cannot easily determine user.config file and user settings are blown with each new revision installed.
Solution: Use the ITEM member to set connection strings at runtime, write code in an Installer class to change the App.Config during install and use the application settings as defaults if a user setting is not found.

Microsoft policy:
Before windows 95, we used ini files for application data.
In the windows 95 - XP era, we used the registry.
From windows Vista, we use ini files although they are now xml based.
The registry is machine dependent. I have never liked it because its getting to slow and it is almost imposible to find the thing you need. That's why I like simple ini or other setting files. You know where they are (application folder or a user folder) so they are easy portable, and human readable.

Is the world going to end if you store a few window positions and a list of most recently used items in the Windows registry? It's worked okay for me so far.
HKEY-CURRENT-USER is a great place to store trivial user data in small quantities. That's what it's for. It seems silly not to use for its intended purpose just because others have abused it.

Registry reads and writes are threadsafe but files are not. So it depends on whether or not your program is single threaded.

Settings that you want to have available in a user's roaming profile should probably go in the registry, unless you actually want to go to the effort of looking for the user's Application Data folder by hand. :-)

If you are developing a new app and you care about portability you should NEVER store data in windows registry since other OS don't have a (windows) registry (duh note - this may be obvious but gets often overlooked).
If you're only developing for Win platforms ... try to avoid it as much as possible. Config files (possibly encrypted) are a way better solution. There's no gain in storing data into the registry - (isolated storage is a much better solution for example if you're using .NET).

Slightly off-topic, but since I see people concerned about portability, the best approach I've ever used is Qt's QSettings class. It abstracts the storage of the settings (registry on Windows, XML preference file on Mac OS and Ini files on Unix). As a client of the class, I don't have to spend a brain cycle wondering about the registry or anything else, it Just Works (tm).
http://doc.trolltech.com/4.4/qsettings.html#details

Personally I have used the registry to store install paths for use by the (un)install scripts. I'm not sure if this is the only possible option, but seemed like a sensible solution. This was for an app that was solely in use on Windows of course.

Usually, if you don't put settings in registry, you use it mostly to get current Windows settings, change file associations, etc.
Now, if you need to detect if your software is already installed, you can make a minimal entry in registry, that's a location you can find back in any config. Or search a folder of given name in Application Data.
If I look at my Document and Settings folder, I see lot of softwares using the Unix dot notation for setting folders:
.p4qt
.sqlworkbench
.squirrel-sql
.SunDownloadManager
.xngr
.antexplorer
.assistant
.CodeBlocks
.dbvis
.gimp-2.4
.jdictionary
.jindent
.jogl_ext (etc.)
and in Application Data, various folders with editor names or software names. Looks like being the current trend, at least among portable applications...
WinMerge uses a slightly different approach, storing data in registry, but offering Import and Export of options in the config dialog.

I believe that Windows Registry was a good idea, but because of great abuse from application developers and standard policies not encouraged/mandated by Microsoft grew into an unmanageable beast. I hate using it for the reasons you've mentioned, there are however some occasions that it makes sense using it:
Leaving a trace of your application after your application has been uninstalled (e.g. remember user's preferences in case the application is installed again)
Share configuration settings between different applications - components

In .NET there really is NOT ever a need.
Here are 2 examples that show how to use Project proerties to do the this.
These examples do this by Windows User Project Properties, but the same could/can be done by Application as well.
More here:
http://code.msdn.microsoft.com/TheNotifyIconExample
http://code.msdn.microsoft.com/SEHE

(late to the discussion but) Short Answer: Group Policy.
If your customer's IT department wants to enforce settings related to Windows or the component(s) you're writing or bundling in, such as a link speed, or a custom error message, or a database server to connect to, this is still typically done via Group Policy, which makes its ultimate manifestation as settings stored in the registry. Such policies are enforced from the time Windows starts up or the user logs in.
There are tools to create custom ADMX templates that can map your components' settings to registry locations, and give the administrator a common interface to enforce policies (s)he needs to enforce while showing them only those settings that are meaningful to enforce this way.

Related

Deciding between GPO and straight registry editing NSIS

I'm writing an NSIS script to upgrade an appliance between versions. The versioning and setup have gotten away from us a bit, as we have many versions in the field, and currently no easy way to upgrade from one version to another. So the first task I have is to write something that they can run on field machines to do everything necessary to bring them to the latest version.
The appliance runs on windows 7. it has 3 users. In the repository for the project there are 4 .msc files that contain group policies to set the appropriate settings for each of these. (computer, non-administrator, admin, appliance)
Is this the right way to go? in trying to power through learning NSIS, it seems easier to write the registry keys directly to HKU /user/... rather than the extra layer of indirection from GPO, given that I'm not doing any sort of distributed system using active directory (which I know approximately nothing about), and just have 3 static users on one static physical machine.
So concise questions:
Which approach makes more sense for my application? GPO files, or direct ntuser.dat editing on the various users.
if GPO makes sense, how do I apply an msc file inside NSIS? double clicking the file works in windows, but then you have the mmc open. oogly. is there a clean way to do it with NSIS?
How does a GPO in the registry under HKCU translate to a system wide policy? it seems to me that what's written to the registry is missing the critical information of which users it applies to (if it applies to a user or group).
Thanks in advance
.msc files usually contain data used by MMC and not policy data, perhaps you mean .adm template files? I don't think you can really apply a .msc file programmatically.
Direct registry editing is probably OK if your application just reads them normally on the other end, otherwise you might need to call gpupdate.
If your policy is stored under Software\Policies then entries in HKLM applies to everyone and entries in HKCU/HKU applies to that user. A normal user cannot change their policy under HKCU because they don't have write access. There is not really a concept of groups when using these keys.

How to make app portable?

I have standard instalations of some programs, and althou they are freeware and i can download them and install on any machine, things are not that easy always. When system crash and i dont have working machine or working internet connection or lan card or drivers for lan card i always struggle to find them and make them work if some dependency file is not on that version of windows.
What i need is to know is how can i make applications portable so i can run them from my usb or just copy them from my usb on pc and run, what dependency files application require, and what files and where specific application install?
It's a complicated story but let's try to summarize. Starts from the part "why?"
I'm an obsessive guy who seriously "hates" installers. I love to have a clean system without bloated in files reg entries and DLL's. Thats why I make nearly all (at least 97%) of programs that I use portable. I made more than 600 up to today and what I can say is;
You need:
1- A program to watch file system (what included after installation)
I use this. Simple and straight (sorry not freeware, but you can find tons of alternates)
http://www.samsunsegman.com/um/
2- A program to watch registry (what changed or included after installation)
I use this in HTML mode. Free fast and simple. And portable in nature.
http://sourceforge.net/projects/regshot/
Now scan the system with these 2, and than run the installer. After open the installed program and make your settings as you want. And than use this 2 program to find the added files and registry entries.
For files, delete them to trash can and take them back from trash in batch (easy to do like that) to the folder of application.
Registry, open the related branches in registry, delete any entries containing addressings like (plugins folder = c:\prog.... etc) After right click on main branch and select export. This is your reg settings...
3- Download this program http://ctuser.net/?reg2exe
This will convert your reg file to an exe file.
4- Download this application http://download.cnet.com/FilePacker/3000-2216_4-10414081.html
Note: Click on "Direct Download Link" if not you'll cnet will welcome you with their installer :)
And with this program (I use this because have no interference with any application) pack the program that you want to make portable. In wizard, first choose your reg-exe file after main programs file. Launcher will execute them with this order. And in setting choose "delete after terminate" will delete the extracted files on exit.
You can discover the further details. This helps you to portabilitize nearly 75% of simple applications.
5- For complicated programs or complicated needs you even can make home made loaders like
Before executing the app, put the user files under appdata folder (that I hate)
Put settings in registry (even with dynamically modified "path" addresses)
Choose which to execute (x86 or x64)
Execute in admin mode if needed
Execute the app... And when application is terminated...
Delete the settings from registry
Take the user files from appdata folder and put under programs folder (usb etc) back.
Delete left-over files under the system...
I just wrote these last ones to make you understand how far you can go. And for all these extra tricks, I use just and just bat files. And I convert them to exe also with this software. http://www.f2ko.de/programs.php?lang=en&pid=b2e (also free)
All the softwares that I use except "uninstall manager" are free. And with this technique, amazing but some of programs are running even faster.
Actually you can just use JauntePE or portable apps packer things but... Jaunte and similar sandbox making programs are so slow and not compatible with all. Even causing crashes. Portable apps approach is a bit bloated regarding to my strict spped and size standards. That's why I do it myself about for 10 years (yes even people was not talking about portability)
Note: I'm not a programmer, and you also don't need to be to do these.
I never released my portables, and you also shouldn't (read EULA's) for respect to authors.
But never forget to demand portable version from all authors. Force them to quit installers ;)
Best regards
inovasyon did a great job!
If you want to make some portable app that will work on every computer you move it to, then 99.9% of apps can be made portable.
If you also expect the app to not leave any files, folders or registry entries behind and not change or break things on the host PC's setup, then that limits things a bit further.
Apps requiring admin privileges to write to protected areas of the registry or file system will break when used on PCs with locked-down privileges.
Apps requiring services to be installed on the host PC will often leave them behind.
You must to know there are apps that are locked to specific PCs - Microsoft's recent versions of Office are a great example of this. They simply will not run when moved to another PC.
Also, you'll need some tools for making portable app: cameyo, thinapp, boxedapp, portableapps, spoon, app-v and other.
Portable applications will run from a flash drive, and from the computer.
Good Luck!
Here is a primer for setting up a portable app using the PortableApps.com tools. They have a page for developers that is quite helpful for some specifics, but the overall process is not well summarized. Here is the general outline for creating a portable application:
1. Investigate your application's footprints
Find all the files, registry locations and settings of the application you want to make portable (make use of point (1) and (2) in inovasyon's answer, and maybe take a look at Zsoft). It is usally a good idea to fire-up a virtual machine and track the application's changes without much clutter.
2. The PortableApp generator
Download, extract, and open the PortableApps.com Platform, and follow [The system tray icon] →[Apps] →[Get More Apps] →[By Category] to install the PortableApps.com Launcher, and NSIS (Unicode) needed to Portabilize your app. Alternatively, but with some added hassle, download both the PortableApps.com Launcher and NSIS Portable (Unicode version) as standalones.
You can now compile a project by running the PortableApps.com Launcher and pointing it to your project.
3. PortableApp layout and structure
Download the PortableApp.com Application Template (search for it here) to structure the data and files obtained in (1.) according to the specifications. Also, download some apps from portableapps.com for some practical examples of how they are structured, and to learn more about the struggles of portability (such as the substitution of drive letters in settings files to correspond to the movement of a portable drive).
As a "Hello World" example, try portability this simple program: helloworld.bat, with content:
#echo off
echo Hello World > log.txt
It writes all local environmental variables to the log file log.txt. You can play around a bit by trying to writing files to an %APPDATA% subdirectory and see if you can make your project redirect it to a portable directory.
4. Additional usage
If you need to do some additional coding that is not achievable with the default .ini capabilities (such as forcing only one instance of an app), add a NSIS script with file location App\AppInfo\Launcher\Custom.nsh to your project. Note that PortableApps.com's custom code guide incorrectly states the file location as Other\Source\Custom.nsh. It is also quite unhelpful regarding the layout of this script. Rather look at examples from other Apps and learn the NSIS syntax by Google-ing a bit.

Where is the guideline that says you shouldn't write to the Program Files area?

Many questions on SO say "Windows developer guidelines" or "windows design guidelines" say that you shouldn't write temporary or program data to the Program Files area, but as far as I can tell none of them actually link to a piece of documentation that says as much. Searching the MSDN has yielded me no results. Windows will make the area read-only, so it can be enforced by the OS, but that doesn't mean developers didn't try to write there anyway (e.g., when porting older, XP and earlier based programs forward.)
I realize that it seems odd to ask about it this late into Windows development (since, as a commenter below pointed out, has been enforced by the OS for more than a decade), but a document that says so is sometimes necessary to satisfy people.
With that in mind, Does Microsoft have a document published stating we shouldn't write application data to the Program Files area, and if so, where is it?
From Technical requirements for the Windows 7 Client Software Logo Program:
Install to the correct folders by default
Users should have a consistent and secure experience with the default
installation location of files, while maintaining the option to
install an application to the location they choose. It is also
necessary to store application data in the correct location to allow
several people to use the same computer without corrupting or
overwriting each other's data and settings.
Windows provides specific locations in the file system to store
programs and software components, shared application data, and
application data specific to a user:
Applications should be installed to the Program Files folder by default. User data or application data must never be stored in this
location because of the security permissions configured for this
folder (emphasis added)
All application data that must be shared among users on the computer should be stored within ProgramData
All application data exclusive to a specific user and not to be shared with other users of the computer must be stored in
Users\<username>\AppData
Never write directly to the "Windows" directory and or subdirectories. Use the correct methods for installing files, such as
fonts or drivers
In “per-machine” installations, user data must be written at first run and not during the installation. This is because there is no
correct user location to store data at time of installation. Attempts
by an application to modify default association behaviors at a machine
level after installation will be unsuccessful. Instead, defaults must
be claimed on a per-user level, which prevents multiple users from
overwriting each other's defaults.
And I'm quite sure that there's similar stuff for every Windows version of the NT family going back to Windows NT 4 or even earlier.
See also this question.
Edit: the original link in this post to the Windows 7 Logo program exists no more. Here you find the current link to the Certification requirements for Windows Desktop Apps. See Section 10, Apps must install to the correct folders by default
In later versions of windows (Vista, 7 and of course server versions) access permission are restricted for "special folders" including "Program Files". Even if your program is elevated to have sufficient privileges to write to this folder it is still a bad idea.
I don't know of any guidelines that state this but there is a list of special folders and what they are meant for. The fact that there is a special folder for nearly all types of data I can image means there is no need to use the program files folder.

Windows Vista, Default Programs API, file format associations, and (un)installers - explosive mix!

My application is a rather well behaved Windows citizen, so when I ported it to Windows Vista/7 I replaced my custom file format association code with support for the Default Programs API. However I ran into a problem when trying to make uninstaller for my application - there seems to be no way to remove file format associations via Default Programs API.
I tried to call IApplicationAssociationRegistration::ClearUserAssociations but it actually removes all associations, including the ones for other applications - completely restoring default state of the OS (which is of course unacceptable).
I tried to call IApplicationAssociationRegistration::SetAppAsDefault to return file format associations to the previous "owner" - but it does not help, because my application handles many unique file formats which the OS does not support and there is no previous "owners". And Windows does not allow to pass empty strings to SetAppAsDefault...
So what do I do? Any good solutions?
I think that you are using the Default Programs API in the wrong way. If I understand correctly the default programs functionality was added by Microsoft due to legal requirements to replace Internet Explorer as the default browser. It offers another set of functionality than the normal file associations used by aplications. If you just have a simple file association to register, I'd suggest you stick to the old behaviour.
From MSDN:Default Programs (Windows):
Default Programs is primarily designed for applications that use standard file types such as .mp3 or .jpg files or standard protocols, such as HTTP or mailto. Applications that use their own proprietary protocols and file associations do not typically use the Default Programs functionality.
Side note: All the considerations below apply even if you modify directly the file associations in the registry instead of using the Default Programs API.
On first run, your application should collect the previous owners of all the file types for which one exists, through IApplicationAssociationRegistration::QueryCurrentDefault and store them in storage your app owns.
On uninstall, your application should use IApplicationAssociationRegistration::SetAppAsDefault to attempt to restore any file association it still owns to the previous owner it has. For associations your app still owns, but don't know previous owners, go to the HKCR registry and delete the corresponding extension, protocol or MIME type entry. Don't touch any associations your app is not the current owner - you'll be overwriting the user's choice.
I certainly wish that the batched backup on first run and cleanup on uninstall were provided as a single API call by the Default Programs API, but until they decide to generalize that behavior for all apps, you're on your own.
Note that the cleanup your application executes on uninstall will be specific for the uninstalling user. Any other users that might have used the application and changed their defaults will not be cleaned up.
You can automate the cleanup for each user by adding a simple per-user task that executes the steps above in the Task Scheduler. The task will be scheduled to execute once and then removes itself from the user task scheduler. The only potential problem with that approach is that since you don't know how many users there will be, it's impossible for you to know when to remove the dll for that task from the machine. Then again, if you leave that dll in the ProgramData folder, it's not a big deal.
The correct code for associating your file extension with an application, is using the Windows Registry settings. Typically this is done to the entire machine (regardless of user) using the HKEY_LOCAL_MACHINE\SOFTWARE\Classes registry hive, which is also accessible more conveniently through the HKEY_CLASSES_ROOT alias (registry shortcut).
Your process involves three steps:
Saving the "old" settings, before installing your application (BTW, it's nice that you are doing that. Many applications simply remove the mapping altogether!)
Creating your own associations. A good example on how to perform this is at Modifying File Associations With Registry Editor. A thorough explanation is on MSDN:
When uninstalling, recover the saved "old" settings from step (1), and rewrite the installed values with these original ones. In case there were no "old" settings, a good citizenship would mean simply deleting the class key altogether from the registry.
One tool to assist in debugging and seeing how class (extension) mappings change is at FileAsoc Windows File Association Editor. It lets you recover file extensions while debugging your application. The webpage also gives a short explanation of how exactly the values are stored.
Hope this helps!
Instead of making the file associations in your app, make them in the installer. Using WiX you can create an installer that sets file associations on install and will remove them on uninstall

Suggested file location that will be editable by all windows users?

I'm building a product that involves
a windows service caching data on the local machine,
user processes reading that data and writing their own data,
the service in turn writing back that data to a server.
Where should I put the data files for this, such that they'll be shared by all users and read/writable? The software will operate in a corporate environment where desktops are sometimes pretty locked-down, so for instance some users won't have write rights to C:\Program Files.
I don't think C:\Documents And Settings\All Users\Application Data\ is a good candidate - I think by default only Admins & Power Users have write access here.
I could use each user's Application Data folder, but this would be a bit of a pain as different people could use each machine ... so it'd be simpler if there was just one shared location.
I'm developing in C# .net 2005, but that's probably not too relevant.
Unfortunately you have no real choice. You must (you really must) call SHGetSpecialFolderLocation to get the path to c:\users\public\AppData (which is the name of the folder you linked above, but on Vista and possibly Windows 7)
Then you MUST create your own app folder therein. And then, you MUST, use the security APIs to modify the ACL of the created folder.
There is NO folder on the system with a default ACL that allows multiple non administrator users to read AND write the same files.
c:\users\public\AppData is the closest. Modifying the ACL of a application folder here seems the best approach. Of course, once one has resorted to ACL modification, the folder really could be created anywhere at all. But that could surprise system administrators and result in weired security holes.

Resources