Archive

Archive for February, 2009

Using External .NET Config Files in a Windows Service

February 18, 2009 Leave a comment

The .NET platform provides an easy way to configure your .NET application using an xml configuration file. At design time, the file is named “App.Config”. When you build your project (console application, Windows service, etc.), the file is renamed to the form [ProgramName].exe.config. The file is deployed in the same directory as the executable. At runtime, the file is automatically picked up from the current directory by the Configuration class.

The single App.config file works pretty well for simple stuff, but at some point it gets unwieldy and you want to separate the configuration into separate files. For example. log4net and Spring.NET both provide mechanisms for using external config files. In a normal deployment scenario (e.g. a console application), it just works.

Often, trouble arises when combining these external configuration files with a Windows service deployment. The built-in configuration classes seem to locate the main config file well enough, but the external files cannot be located. They are attempted to be loaded from %SystemRoot%\System32. Why? This is the location of the net command, which is the host process for the service. I suspect the implementers of the external configuration files refer to the CurrentDirectory of the process, instead of the file location of the executable module.

You can fix the problem by setting the CurrentDirectory of the process:

<!–
{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Envy Code R VS;}}{\colortbl;??\red0\green0\blue0;\red227\green213\blue193;\red64\green0\blue128;\red1\green0\blue1;\red46\green83\blue209;\red48\green95\blue182;\red37\green146\blue65;\red163\green21\blue21;}??\fs24 \cb2\highlight2 \cf3 var\cf0 \cf4 process\cf0 \cf5 =\cf0 \cf6 Process\cf5 .\cf4 GetCurrentProcess\cf0 ();\par ?? \cf3 if\cf0 (\cf4 process\cf5 .\cf4 MainModule\cf0 \cf5 !=\cf0 \cf3 null\cf0 )\par ?? \{\par ?? \cf3 string\cf0 \cf4 newFilePath\cf0 \cf5 =\cf0 \cf4 process\cf5 .\cf4 MainModule\cf5 .\cf4 FileName\cf5 .\cf4 Substring\cf0 (\cf7 0\cf0 ,\par ?? \cf4 process\cf5 .\cf4 MainModule\cf5 .\cf4 FileName\cf5 .\cf4 LastIndexOf\cf0 (\cf8 @”\\”\cf0 ));\par ?? \cf6 Directory\cf5 .\cf4 SetCurrentDirectory\cf0 (\cf4 newFilePath\cf0 );\par ?? \}}
–>

   25 var process = Process.GetCurrentProcess();

   26 if (process.MainModule != null)

   27 {

   28     string newFilePath = process.MainModule.FileName.Substring(0,

   29         process.MainModule.FileName.LastIndexOf(@”\”));

   30     Directory.SetCurrentDirectory(newFilePath);

   31 }

If you like, you can put this code into the OnStart method of your service. But you might need the info before that. In that case, put the code as early as possible.

 

Credit goes to Jose Joye, who posted this idea back in 2005.

Reblog this post [with Zemanta]
Categories: Uncategorized
Follow

Get every new post delivered to your Inbox.

Join 124 other followers