Thursday, October 1, 2009

Common FAQs - App configs, NLog, UAC, Folder Enumeration etc

Although App configs bring flexibity and configurability to our applications, working with it can be quite confusing. I will clear atleast two most common questions that arise in our minds

a) Can we load a windows application App.Config from a different Location ?

Answer: Yes. We do not necessarily need to have the app config in the same directory as the executable. We know that every windows app has atleast one app domain to run in, so we fool the app domain by setting one of its internal variables to locate to a web config from a different location.

Use the following line of code to do so.
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", _path );
Here _path = path to your distant location App.config.

b) How to Make my Windows App re-read my App config or Reload my App config without restarting the application?

Answer: Use the following piece of code, which sets a private variable reflectively and fools the configuration manager to reload the config file.

RuntimeFieldHandle initStateFieldHandle = typeof(System.Configuration.ConfigurationManager).GetField("s_initState", (BindingFlags.NonPublic BindingFlags.Static BindingFlags.ExactBinding)).FieldHandle;

FieldInfo fi = FieldInfo.GetFieldFromHandle(initStateFieldHandle);
// retrieve reference to registered client variable
fi.SetValue(null, 0);


c) Can we set the Log File Directory dynamically in NLog?

Answer: As we know NLog is a great component for Logging in .Net applications. It aliveates the users from the hassles of creating the infrastructure to enable logging in .net applications. I came across a similar issue while working on UAC stuff to create a Log File in a different directory based upon the Operating system.


Nlog has provided us with some functionality to inject the programatically generated Path/Log file location into the configuration specifed in config files. Take a look at the highlighted piece of code in the following configuration section. We could see a variable gdc:logdirectory. This pertains to a variable name logdirectory which has been set somewhere globally.



xsi:type="File" layout="${message}"
filename="${gdc:logdirectory}/Log/MyLogFileName.log"

archiveFileName="${gdc:logdir}/Log/MyLogFileName.{##}.log" archiveAboveSize="1048576" archiveNumbering="Rolling" concurrentWrites="true" maxArchiveFiles="20" keepFileOpen="false" encoding="iso-8859-2" />

To Set the variable we must use the following piece of code at an appropriate location eg: Static constructor, class initializer.Etc. so that before the logging code is called, we have the value set.

NLog.GDC.Set("logdirectory", ComputedLogDirectory);



c) Can we merge two configs ??
Answer: Aha... that goes for a blog of itself.... watchout for my next blog.