I solved this partially, but had to make the assumption that my setting lay in a certain part (appSettings) of the file. I could get away with this because, while the settings were logically user settings, each user already has their own config file.
A Microsoft config file is a specially-structured XML file, Microsoft have a dedicated assembly to work with one, System.Configuration, and I'd really have expected any contributor to have known this, certainly if they felt they knew enough to contribute at all. So suggestions based on System.Xml and worse, System.IO, just got an "F" as far as I was concerned. I took them as mostly facetious, and I'm left wondering why somebody participates in an information sharing site, if not to be helpful. But anyway, my solution relies on System.Configuration.
In pseudocode for brevity:
- I can use ConfigurationManager.OpenMappedExeConfiguration to open any old file. This is, I guess, well-known, and returns a Configuration object which is a logical view of the file. It's funny, even if the file doesn't exist on the disk, the Configuration is non-null.
- By assuming my setting lies in the appSettings section of the file, I can just use the resulting Configuration's AppSettings property to hone in on the relevant section. I seem to remember that my old code supported any section, which bulked the code out a lot. Again, even if the file doesn't exist physically, Configuration.AppSettings was a valid object.
- When I have the app Settings Section property, I can look at the .Settings property to see what values are there. appSettingsSection.Settings is basically a dictionary of key.value pairs, dressed up as a (Microsoft) KeyValueConfigurationCollection. If the file doesn't exist, appSettings.Settings pointed to a perfectly valid, but empty, collection,
- I can see if my key already exists just by doing a standard dictionary .Contains call on my ElementCollection.AllKeys property
- Bear in mind that we're dealing with key/value pairs here. If we're working with an existing key, we simply get/set element[key].Value, whereas if we're writing a new key, we have to create a new (Microsoft) KeyValueConfigurationElement and Add it to the collection. This class has a handy constructor which just takes the (string) key and the (string) value. One of the other things my original code did was to read/write any serializable object, far more than I needed this time around.
- If I'm writing, I need to remember last of all to Save the Configuration. If you're writing, the file is either updated or a clean one created.
That's it. I'm guessing any of the current readers already knew all this, but I hope it might be useful to future readers. I found it useful to collate this, it took a while to put the pieces together, so it will hopefully save people time at least.
The reason I couldn't share the original code, by the way, was because I don't own either the code itself, or the copyright. In my jurisdiction, it is common for the employer/client to own code written by the employee/consultant, at least while working on their time, and I was no exception. But I only have experience of the UK and the USA, so other jurisdictions might be different. And, people who aren't professionally involved in software development might be subject to different rules altogether. Lastly, I've found over the years that many software developers are ignorant of legal issues altogether.