1

In my Application I use Common.Logging library in order to abstract logging functionality. In startup assembly it was configured (in app.config file) to work against Log4Net library. There are established some Appenders: ConsoleAppender, RollingFileAppender, TraceAppender. Everything works fine in the single AppDomain. However I have found that logging does not work in the newly created AppDomain. i.e:

Logger.Info( "Logging works here" ); // Logging works here

var appDomain = AppDomain.CreateDomain(
                              "AppDomain." + componentHost.FullName,
                               AppDomain.CurrentDomain.Evidence,
                               AppDomain.CurrentDomain.SetupInformation );

var proxy = (IComponentHost) appDomain.CreateInstanceAndUnwrap(
                               componentHost.Assembly.FullName,
                               componentHost.FullName,
                               false,
                               BindingFlags.Default,
                               null,
                               new object[] { },
                               null,
                               null );

proxy.Init(); // Logging does not work in Init() method stack

I'm trying to find a solution, both using app.config configuration as well as Common.Logging API (i.e LogManager.Reset() method), but it doesn't solve a problem.

How can I force Common.Logging / Log4Net to work properly in newly created AppDomain? Please for help.

sgnsajgon
  • 664
  • 2
  • 13
  • 56
  • why aren't you creating and init()'ing inside the new app domain? You are creating the new instance using the new app domain but are initializing in the old or default app domain. – T McKeown Jan 02 '14 at 15:30
  • The sample code is the part of a larger module, where I create several different `IComponentHost` instances, each of them has to operate in the isolated AppDomain. Moreover, the parent module is responsible for managing and releasing of created AppDomains. – sgnsajgon Jan 02 '14 at 15:39
  • yes, but you are getting an object returned from a different app domain. This is remoting, your object may not operate correctly. Have you tried to invoke using a thread created from the app domain you've created and NOT the thread that is tied to a different app domain? – T McKeown Jan 02 '14 at 15:41
  • this links discusses that what you are doing is remoting, any time you pass an object from 1 app domain to another IS remoting and I believe your init() is not working because it is being run on the WRONG domain.http://www.shujaat.net/2011/01/wpf-messaging-using-net-remoting.html – T McKeown Jan 02 '14 at 15:47
  • Yes, I have tried. When I do all action in the `IComponentHost` default constructor, not in `Init()` method, the result is the same. Logger still doesn't work. – sgnsajgon Jan 02 '14 at 15:49
  • well, you have to eliminate the remoting from the equation. What error do you get when you run the init() from within the new app domain? – T McKeown Jan 02 '14 at 15:50
  • I do not have any error. Everything in `IComponentHost` work as was intended - network connections, Autofac, custom business logic. No errors, no problems, just no logging. – sgnsajgon Jan 02 '14 at 15:53
  • Furthermore, I know that there is a solution for similar problem, if only Log4Net is used alone, without Common.Logging abstraction. The configuration just need to be reloaded using Log4Net configuration API. But I don't know solution, when Common.Logging is engaged to the game. – sgnsajgon Jan 02 '14 at 16:00

2 Answers2

1

From the code you show, it looks like you're not providing a configuration file for your app domain. It's been a few years since I've done this, but if I recall correctly, the configuration file for a new app domain is empty by default.

Here's an example of how to use the AppDomainSetup class:

AppDomainSetup ads = new AppDomainSetup();

ads.SetConfigurationBytes( Encoding.UTF8.GetBytes(
@"<configuration>
  <system.data>
    <DbProviderFactories>
      <remove invariant="System.Data.SqlServerCe.3.5"></remove>
  </DbProviderFactories>
</configuration>" ) ); 

(Credit to Tom Overton for the code sample.)

See http://social.msdn.microsoft.com/Forums/vstudio/en-US/a23ff0ad-8a4c-4aaf-8281-dcc7e840f8a5/assigning-appconfig-to-appdomain?forum=clr for his explanation of this issue.

Terry Lewis
  • 397
  • 2
  • 8
  • 1
    I noticed that my problem appeared only in Integration Tests fired from Resharper's NUnit runner. It didn't occurr during 'real' application flow. In R#, we have resolved problem by imlementing stream redirection to master AppDomain. Thank You for reply. – sgnsajgon Jul 24 '14 at 20:05
  • 1
    @sgnsajgon You wrote "In R#, we have resolved problem by imlementing stream redirection to master AppDomain". Could you please explain the details? – SKINDER Nov 10 '16 at 16:05
1

I have a similar issue with log4net. I used XmlConfigurator.Configure() without parameters that uses Assembly.GetCallingAssembly() to get configuration file. I replaced it with:

var configFile = new FileInfo(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
if (!configFile.Exists)
    throw new Exception($"Failed to find configuration file '{configFile.FullName}'");
XmlConfigurator.Configure(configFile);
SKINDER
  • 950
  • 3
  • 17
  • 39