Wednesday, October 12, 2011

Refreshing Settings and dll.config Files

Having worked on plugin-based architecture and projects involving a number of assemblies there has always been a bit of a bad smell to .Net's implementation for configuration settings files; In particular, the use of Settings.Default. I really like how Settings.Default wraps configuration settings presenting them as strongly typed values. What I hate about it is how it uses the DefaultSettingValueAttribute to specify the default value in the event that a setting cannot be loaded. Why is Settings.Default a problem?

1) Because it hides problems with configuration. Essentially it means if you don't have a configuration setting specified, it will use the attributed value by default. This can lead to spitting venom at the computer as you try to spot a type-o in a the configuration XML six months after the fact when that mail server name changes and you realize it's been using the attributed value and absolutely refuses to accept your configuration setting.

2) Because at runtime you may want to have a service running and be able to change configuration settings and have the service pick up those changes. Unfortunately you're out of luck because while user settings can be reloaded, application settings cannot. The service needs to be stopped and restarted to accept the new configuration settings.

3) Because in cases where you have support assemblies in your project, the pain comes in that while it might be nice and sensible to have each assembly's settings located in their .dll.config file (which Visual Studio produces for you) by default, Settings.Default will only look at settings in the calling application's .exe.config file, even if you place the .dll.config file in the runtime folder. This means if you have 30 configuration settings across six assemblies, you're manually copying across 6 configuration sections and 30 settings into the app's .exe.config file. Now you may be perfectly able to build an NAnt task to do this, but it leaves you with a painfully large and convoluted configuration mess in the .exe.config file.

Now all of these problems can be avoided if you choose to load and parse configuration settings yourself using ConfigurationManager and the like. However, you lose that nice encapsulation that Settings does give you. There may also be solutions on the web for one or more of these issues, but I never was able to find one.

So I set about to change that.

Source Code

SettingsExtension.cs is an extension method you can utilize to refresh any Settings instance from it's assembly's .config file. This means if you have a DLL containing a Settings & associated app.config section and deploy the .dll.config file, you can call the Refresh() method to retrieve the values at any time from the .dll.config file. It works for .exe.config files as well, however calling it on a DLL's Settings will not refresh from .exe.config settings if you've modified settings there. The DLL only discovers its own configuration file.

What this means is that if you have a project with an EXE and X number of supporting DLLs, and some of those DLLs want to use configuration settings, you can copy the .dll.config files into your deployment and as long as they have a call to Settings.Default.Refresh() (I.e. from a static Constructor) you can ensure that that DLL will always use the values from its .dll.config file.

Additionally if you want to get creative, you can now set up a File Watcher on a .exe.config file (or .dll.config files) and when it detects a change, call the .Refresh() on the Settings.Default instance to reload those changes.

Looking through the code it should be pretty easy to see what it's doing. It looks for the Setting's assembly's config file, applicationSettings section group, and section for settings, then uses reflection to go through all known settings properties and update them with whatever is found in the file.

An added feature is support for an optional Refresh Listener which the refresh method can communicate back statuses about what it is processing and if it encounters any errors. Exceptions are non-fatal, the tool will report them back and continue. The reporting includes a message and a TraceLevel as an indication of what went wrong. Simply register a method using SettingsExtensions.InitializeListener() method in order to receive messages.

I've tested the implementation with most Settings-supported data types but there might be a few that need some special parsing.

Wednesday, October 5, 2011

Something's fishy with Google...

It might be time to start lining my room with aluminium foil but something very strange has been happening relating to when I try to install Google software on my machine. This is a fairly new machine running Windows 7 Pro. I'm anything but a MS Fanboi but being a MS technology stack developer has paid the bills quite nicely over the years so who am I to start bitching. One thing I do not like is IE, so as soon as the system was up, I installed Firefox and uninstalled IE. This led to some rather annoying but laughable problems like when applications cannot seem to figure out that I don't have IE, they try launching HTML files in MS Word.

A while back I had a play with Chrome on the office laptop and decided to try it at home. All went well until I started noticing that my Firefox browser would hang, and then Windows 7 would completely hang just out of the blue when browsing. (Not using Chrome at the time) This started to get really annoying because task manager etc. didn't even respond. I started digging around and noticed a few other people having trouble with Chrome and Firefox playing nice together on Windows 7 / Vista. I uninstalled Chrome and the problem vanished. For the record I do not use any Google apps such as toolbar etc. either. I passed it off for some weird glitch between the two systems and something with Win 7 falling over after not figuring out how to resolve their differences. Disappointing to say the least, but I prefer Firefox as a browser to Chrome.

However, recently I decided to dust off my old Java books, install the latest Eclipse, and have a peek at the Android SDK. All was fine until I launched the Android SDK Manager then decided to do a bit of browsing while it was downloading my selected SDK versions and such. Within 10 min Firefox had hung again and the system went completely dead!

So really now, Google, What the Farq are you installing with your software that is getting completely shirty with Firefox and/or Windows 7?! My guess is that the SDK downloader is using netcode shared with Chrome that is in some way incompatible with whatever Firefox is using. Or is it something more sinister? While I have found some references of other people having similar problems I haven't seen anything that remotely looks like a solution or acknowledgement that there is a problem.

The question is, if I sacrifice my (relatively minor) preference for Firefox in favour of Chrome, will I be able to browse and utilize the Android SDK without having my machine lock up? And more importantly, will I wake up the next morning without finding a completely new preference shift from the soda I drink to the car I drive due to some form of wifi-induced subliminal suggestion? :)