log4net – changing log file location on runtime

In one of our application we are using apache log4net, initially we were logging to the “logs” folder, which was located in the application installation folder. When we were testing this application on different Windows operating systems, it was not generating logs when we ran our application under least privileges account.

Where should we log then?

We found three different locations where user don’t need alleviated privileges to read/write.

  • %USERPROFILE% – C:\Users\UserName
  • %LOCALAPPDATA% – %USERPROFILE%\AppData\Local
  • %APPDATA% – %USERPROFILE%\AppData\Roaming

But wait, our application have two different modules, one is a desktop application, and other is a Windows service. We wanted to have same logging location for both. Above options did not fully qualified for that. As service will always run under one account, but our desktop application could be used by any logged in user, so different log locations if we use above mentioned options.

Now what?

Hmmm, we found another location which was still least privileged, and could be shared by multiple application modules easily.

%ALLUSERSPROFILE%

Where did it pointed to?

  • Windows XP/2000/2003 – C:\Documents and Settings\All Users
  • Windows Vista/7/8 – C:\ProgramData

That suited us well. Then we looked how we can specify these locations in log4net configuration. First solution we found is to use substitution key option in file parameter value as below. results were positive after execution.

  
    
      
      
    
    
      
      
    
  

I wanted to peek under the hood, so used Reflector to examine the log4net assembly. So when configuration are read from XML, value attribute is checked for substitution key of each “param” element. A key is specified using $ and {} as ${KEY}, and values are mapped from environment variables. So if that key is available in your environment variable then it can be substituted.

You can test these keys using following code.

string data = log4net.Util.OptionConverter.SubstituteVariables("value of %ALLUSERSPROFILE% is ${ALLUSERSPROFILE}", Environment.GetEnvironmentVariables());
Console.WriteLine(data);

I have found some other solutions too, which I will post later when I can understand them more.

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.