Use environment variable in filePath in File Configuration Source

Topics: General discussion, Logging Application Block
Nov 19, 2009 at 7:27 PM

In order to allow a standard user under UAC to modify the EntLib Logging configuration, I've moved the location of the logs and the logging configuration to the \programData\MyCompany\MyApp folder.  In the logging configuration, I can use an environment variable in the file path, like this:

<listeners>

<add fileName="%ALLUSERSPROFILE%\mycompany\myapp\myapp.log"

I'm using %ALLUSERSPROFILE% instead of c:\programData because of course you can't guarantee c:\programData is correct.  Fortunately, using the environment variable here works.  Unfortunately, it does not work in the app.config to point the EntLib to the configuration, and I've had to resort to using the hard-coded path.  Is there a way to tell the File Configuration Source to use a well known system folder (Environment.SpecialFolder.CommonApplicationData)?

<enterpriseLibrary.ConfigurationSource selectedSource="File Configuration Source">

<sources>

<add name="File Configuration Source" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"

filePath="c:\ProgramData\MyCompany\MyApp\MyApp.Logging.config" />

Would like this to be something like:

filePath="%ProgramData%\MyCompany\MyApp\MyApp.Logging.config" />

 

 

Nov 20, 2009 at 9:03 AM

Hi,

As far as I know, using environment variable on the file configuration source thru config is not supported.

Valiant Dudan
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

Nov 20, 2009 at 3:55 PM

Thanks for your reply.  This is a huge deal, as being a good UAC citizen and using EntLib means placing the configuration outside of app.config.   If you can't point to a known location using an standard environment variable you're left with having to write code to assign the location and modify the app.config during installation.  Either I'm missing something or there are way too many programmers writing desktop apps not testing as a standard user with UAC turned on, AND testing with XP.

I've looked into the EntLib source and I think I see where it's calling

Environment.ExpandEnvironmentVariables

On the file trace listeners, and where it might be appropriate to call the same on the file configuration source, but the source for EntLib it daunting and making sure you're in the appropriate place isn't a no-brainer.

 

            Environment.ExpandEnvironmentVariable

 

Feb 3, 2010 at 6:21 PM

esaulsberry:

Did you ever find a workaround for this issue? I am facing the same problem right, since I do not want to hard code my file path either, I was considering using Environment variable but had no success.

Feb 8, 2010 at 7:16 AM

I think the only workaround would be to modify the source code.

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

Apr 28, 2010 at 8:06 PM

For anyone looking for a solution to this, here is how I modified the EntLib to handle this:

Modify the constructor of the FileConfigurationSource class in the [solution][core]Common[configuration]FileConfigurationSource.cs file.

public FileConfigurationSource(string configurationFilepath)
{
    // Elton - Allows use of environment variable in the app's config file to point to a EntLib file configuration source.
    // Note: On XP, the installer variable [CommonAppDataFolder] refers to C:\Documents and Settings\All Users\Application Data
    // although &ALLUSERSPROFILE% refers to C:\Documents and Settings\All Users  To make things happy, on XP
    // we have to stick the extra path info in the string.
    string basePath = configurationFilepath;
    System.OperatingSystem osInfo = System.Environment.OSVersion;
    const string targetSysVar = "%ALLUSERSPROFILE%";
    if (osInfo.Platform == PlatformID.Win32NT && osInfo.Version.Major <= 5 && basePath.ToUpper().Contains(targetSysVar))
    {
        const string replacementValue = @"%ALLUSERSPROFILE%\Application Data\";
        basePath = basePath.Replace(targetSysVar, replacementValue);
    }
    string configFile = Environment.ExpandEnvironmentVariables(basePath);

    //if (string.IsNullOrEmpty(configurationFilepath)) throw new ArgumentException(Resources.ExceptionStringNullOrEmpty, "configurationFilepath");
    //this.configurationFilepath = RootConfigurationFilePath(configurationFilepath);
    if (string.IsNullOrEmpty(configFile)) throw new ArgumentException(Resources.ExceptionStringNullOrEmpty, "configurationFilepath");
	this.configurationFilepath = RootConfigurationFilePath(configFile);

	if (!File.Exists(this.configurationFilepath)) throw new FileNotFoundException(string.Format(Resources.Culture, Resources.ExceptionConfigurationLoadFileNotFound, this.configurationFilepath));
	EnsureImplementation(this.configurationFilepath);
}
Once you've done this, your application app.config can now contain the environment variable pointing to your EntLib configuration file.
  <enterpriseLibrary.ConfigurationSource selectedSource="File Configuration Source">
    <sources>
      <add name="File Configuration Source" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=4.1.1.0, Culture=neutral, PublicKeyToken=127192FD81A7DA32"
        filePath="%ALLUSERSPROFILE%\MyCompany\MyApp\MyApp.Logging.config" />
    </sources>
  </enterpriseLibrary.ConfigurationSource>