1
votes

I am trying to create a simple file logger for my windows service, but the file isn't being written to. Here is my app.config file:

<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  </configSections>
  <connectionStrings>
    <add name="MyAppConnectionString" connectionString="Data Source=.;Initial Catalog=MyApp;Integrated Security=True;MultipleActiveResultSets=True" />
    <add name="MyAppEntities" connectionString="metadata=res://*/MyAppModel.csdl|res://*/MyAppModel.ssdl|res://*/MyAppModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=.;Initial Catalog=MyApp;Integrated Security=True;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" />
  </connectionStrings>
  <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  </startup>
  <system.web>
    <roleManager enabled="true" defaultProvider="MyAppSqlRoleProvider">
      <providers>
        <add name="MyAppSqlRoleProvider"
             type="System.Web.Security.SqlRoleProvider"
             applicationName="MyApp"
             connectionStringName="MyAppConnectionString"/>
      </providers>
    </roleManager>
  </system.web>
  <log4net>
    <appender name="FileAppender" type="log4net.Appender.FileAppender">
      <file value="C:/logfiles/MyAppAlarms.txt" />
      <appendToFile value="true" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %message%newline" />
      </layout>
    </appender>
    <root>
      <level value="ALL" />
      <appender-ref ref="FileAppender" />
    </root>
  </log4net>
</configuration>

I know there are other posts similar to this one, but I've read them and tried seemingly everything in them and I wasn't able to get anywhere. I tried putting the same tag above in a console app and that worked. I tried copying and pasting my app.config to the C:\ drive and referencing it using this in my AssemblyInfo.cs:

[assembly: log4net.Config.XmlConfigurator(Watch = true, ConfigFile = @"C:\app.config")]

but that did not work. I was able to attach to the service using a debugger, but I'm not sure how I can use that to my advantage here. Nothing is throwing an exception. I tried writing to the same file using a StreamWriter and that worked, so I know it's not a write-permissions issue.

I'm at a loss for what to try next. Is there a way I can get some debug info so I can figure out what is wrong? I tried enabling internal debugging and running DebugView, but I wasn't seeing anything except low-level networking messages. I also tried setting log4net debug=true, but I think this writes to the console which doesn't help in a service.

4
Enable internal log4net debugging like it's described here and see if this helps you figure out the issue: haacked.com/archive/2006/09/27/Log4Net_Troubleshooting.aspxCole W

4 Answers

1
votes

I was also facing the same issue, I used below statement while my service runs for configuring logger.

XmlConfigurator.Configure();

and it worked.

0
votes

Check to see that the app.config file is named correctly. If your service executable is MyService.exe, then the configuration file should be named MyService.exe.config.

I've been bitten by this several times and it's now one of the first things that I check.

See also: App.Config vs. AppName.exe.Config

0
votes

If you are debugging a service, make sure that you have Capture Global Win32 enabled in DbgView. When you set log4net debug=true, then you should see the messages both on the console and in dbgview.

If you have a log.Debug call at the start of the program before you call ServiceBase.Run( ..) command, then you should be able to run your exe directly from a command prompt and it should initialise the logging and hence any internal logging messages before it displays the error message that says you can't start a service from the command line. This may give some indication of what the issue it. (Of course you have to be aware that by doing this you may be running the program under different credentials.)

Also if you want to run your whole program in non-Service program from the command line, you can usually do that by changing a few lines.

Your service will probably start using something like

static void Main()
{
     log.Debug("Start Up");
     ServiceBase.Run(new MainService());         
}

and you can change this to something like

static void Main()
{
     log.Debug("Start Up");
     MainService ms = new MainService();
     ms.OnStart(null);
}

or if you want to be able to switch without recompiling, then something like

 // The main entry point for the process
    static void Main(string[] args)
    {
       log.Debug("Start Up");

        string cmdLine = args.Length == 0 ? "" : args[0].ToLower().Substring(1);

        // If we are debugging or if we have been passed the /NonService 
        // commandline, then start the program in non-service mode.

        if (System.Diagnostics.Debugger.IsAttached 
             || string.Equals(cmdLine, "NonService" , System.StringComparison.CurrentCultureIgnoreCase))
        {
            MainService ms = new MainService();
            ms.OnStart(null);
        }
        else
        {
            ServiceBase.Run(new MainService());
        }
    }
0
votes

The service that writes to the log needs to have administrator rights to access the Security log in Event Viewer. You can test this by starting the service using an account with administrator access. Don't use an account with administrator access in your production environment, but just as a temporary test.

To fix it create a custom event log. It will bypass the need to access the Security logs.

<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender" >
      <logName value="System" />
      <applicationName value="AppName" />
      ...
</appender>