16

In my app.config I put

<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
  <file value="%programdata%/log-file.txt"/>

but it didn't work. Any ideas?

Jader Dias
  • 88,211
  • 155
  • 421
  • 625

4 Answers4

28

The log4net syntax for expanding environment variables is "${Variable}" e.g.

<file value="${LOCALAPPDATA}\GojiSoft\GojiLog\log.txt" />
Tim Lloyd
  • 37,954
  • 10
  • 100
  • 130
  • is this syntax log4net specific? will it work in other settings? – Jader Dias Jul 26 '10 at 19:08
  • 3
    @Jader This is specifically implemented in log4net. – Tim Lloyd Jul 26 '10 at 19:10
  • 1
    While your example works fine, ${PROGRAMDATA} doesn't work. But I think it's some kind of permission problem. – Jader Dias Jul 26 '10 at 19:13
  • 2
    @Jader The owner of the process needs to have permission to write to the specified location. – Tim Lloyd Jul 26 '10 at 19:13
  • do you have link to the reference page which talks about this log4net syntax? – Jader Dias Jan 13 '11 at 17:16
  • @XMLforDummies I'm afraid I cannot find any specific documentation for this feature. However, the feature simply allows environment variables to be expanded when the syntax detailed above is used. What aspect were you unsure about? – Tim Lloyd Jan 13 '11 at 17:23
  • I'm trying to name the log file accordingly to the calling assembly. I couldn't find a suitable variable. – Jader Dias Jan 13 '11 at 17:32
  • @XMLforDummies I see. OK, this question is about environment variables which have nothing to do with log4net specifically. Log4net will just blindly ask the OS for the variable value. – Tim Lloyd Jan 13 '11 at 17:36
  • These names are Windows environment variables. Listed here: http://ss64.com/nt/syntax-variables.html So for services logging to c:\ProgramData\..., use "ALLUSERSPROFILE" or alternately "ProgramData". For apps installed locally just for the current user, used LOCALAPPDATA. – Curtis Yallop Jun 13 '14 at 20:59
  • This doesn't work cross platform because '\' is not a path separator on linux it will instead log to a file named 'GojiSoft\GojiLog\log.txt' directly in the local app data folder. – trampster May 11 '15 at 05:15
21

Resurrecting an old thread here, but I encountered the same issue and thought I'd share.

${PROGRAMDATA}, as discussed in the comment thread of the other answer, didn't work for me (same as for OP). However, I saw a comment somewhere about it being case sensitive. Tried ${ProgramData} and sure enough, it worked fine.

teleute00
  • 561
  • 6
  • 25
  • Had the same experience. I had to use LOCALAPPDATA all uppercase for it to work. LocalAppData fails. – Robert Graves Nov 18 '13 at 20:47
  • Hmmm...must be a difference in versions of something - whether it's Windows, compilers, log4net itself, I'm not sure though. – teleute00 Nov 19 '13 at 00:18
  • Pay attention "ProgramData" means every user shares the same log. – Polluks Jan 22 '19 at 15:11
  • and I tried out all kind of path (localappdata, appdata, programdata) with different cases and none works. It always ends up creating folders like "${ProgramData}". in the bin folder. So annoying – Welcor Jan 11 '20 at 21:27
2

Use ${APPDATA} instead of ${LOCALAPPDATA}

Leo
  • 21
  • 1
0

We have found that when using Log4Net with DotNetCore and the Microsoft.Extensions.Logging.Log4NetProvider extension method environment variables are not passed through. This is because the log4net configurator is configured by parsing the log4net config file into XML before passing it to the log4net configurator which bypasses the environment variable substitution. However, you can override properties by doing the following:

hostBuilder.ConfigureLogging(logBuilder =>
            {
                var logsPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
                logBuilder.AddLog4Net(new Log4NetProviderOptions
                    {
                        PropertyOverrides = new List<NodeInfo>
                        {
                            new NodeInfo
                            {
                                XPath = "//appender[@name='rollingFile']//file",
                                Attributes = new Dictionary<string, string>
                                {
                                    {
                                        "value", Path.Combine(logsPath, "Application.log") 
                                    }
                                }
                            }
                        }
                    });
            });
<log4net>
  <root>
    <level value="INFO" />
    <appender-ref ref="console" />
    <appender-ref ref="rollingFile" />
  </root>
  <appender name="console" type="log4net.Appender.ConsoleAppender">
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%date %level - %message%newline" />
    </layout>
  </appender>
  <appender name="rollingFile" type="log4net.Appender.RollingFileAppender">
    <file value="Application.log" /> <!--This is overidden at run time. Based on the appender name: rollingFile.-->
    <appendToFile value="true" />
    <rollingStyle value="Size" />
    <maxSizeRollBackups value="5" />
    <maximumFileSize value="10MB" />
    <staticLogFileName value="true" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%date [%thread] %level %logger - %message%newline" />
    </layout>
  </appender>
</log4net>
Yerttle
  • 28
  • 4