On a Delphi programmer's group on Facebook the other day, someone asked a question about configuration files. They were going to use an INI file to hold their data, and someone suggested the Registry. I chimed in that I find INI files superior to Registry files, with the provision that perhaps one exception to that might be if your application needs to configure where its textual configuration files are. The reasons why textual configuration files (in json or ini format) are better than the registry are:
- Because it's easier to back up and restore application state.
- Because for your support people, reading and inspecting a text file is easier than finding and inspecting the registry, which is in the end like one enormous INI file that describes the state of your entire system.
- Because even if the system won't boot any more, it's easy to get that configuration data and copy it off that machine, just by booting from a live CD image like GPARTED or by slapping a completely dead PC's disk in another machine after the motherboard died. In my career this has turned out to be a good choice when customers were told to make a backup and they didn't. Data recovery has saved my customer's bacon when they didn't do the backups they were taught and told to do.
- In my automated bug report submission systems, using MadExcept (or you could use EurekaLog), I find it helpful to attach log files (showing what happened to the app recently, on the client and the server side) and even some of the configuration files, so you know what options the user has configured.
- In some domains we might even check the configurations into version control, or keep backup copies of configurations. It's harder to do that with a registry.
Some interesting technical questions that remain:
- Where should data files, including configuration files be stored? For state which is different for each user, I believe in the user's appdata folders, either Local or Roaming, under a Subfolder named by your company name, with a Subfolder under that for your product name.
Similarly folders under c:\ProgramData should be used for global data that is not different for each user who logs in. So for AwesomeSoft's product SuperTool, on my computer, C:\Users\warren\AppData\Local\AwesomeSoft\SuperTool is used. If the installer version is known and this folder are backed up, then your entire application state can be backed up and restored without even backing up the program files folder. Perhaps a local database or data file might also automatically live here if it hasn't been configured and moved elsewhere.
- Even back in Windows XP era (2002) Microsoft has given clear guidance that non-system privileged processes should not have write access to the Program Files folders. In order to preserve system stability, only the installer, which operates in an Elevated privilege level, and is started by a person with appropriate system administrative role, should be able to write to the program files folder. I consider hacking NTFS permissions on Program Files to be a bad practice, on end user machines. What I think is kind of hilarious though is that in 2016, Microsoft SQL Server 2016, still defaults to primary SQL Table data file storage under Program Files folders, instead of moving that global state data to Program Data where Microsoft's own guidance would have suggested they put it. What do you do when even Microsoft's left hand doesn't follow Microsoft's right hand? I would say, you do what is right, what is a solid engineering principle. Protect users and their systems by separating your binary code and non-user-defined static state (maintained by installers and patch updaters) from your user defined static state (your data folders).
- When if ever are binary configuration files appropriate? I would say, only when the problem domain or technical requirements cannot be met with a text file. For example, if the configuration files contain a million entries and really just needs to be a key-value store. In that case, I would say, you should use a proven binary container like SQLite, and not invent your own shabby one, or use some unmaintainable binary blob technology that you found on the internet, like that b+Tree algorithm you found somewhere randomly on the internet. Binary files are opaque, testing binary file reads/writes is a harder problem, and inspecting that binary file for damage becomes a difficult task, unless you choose something like SQLite that already has tests, and file integrity checking already built.