32

I'm writing a small file conversion utility. Files get automatically converted when they are dropped into a directory.

I'm using NLog for logging. Besides a central log file which is configured using NLog.conf (and which receives all messages generated), I'd like to create one additional log file for each input file, having a similar name and containing all log messages written during the conversion process.

Unfortunately I seem to be unable to find out how to properly add a new file target together with the appropriate rule during runtime. I want all Logger objects to write to the new log file during the conversion process.

I tried something like

var logfile = new NLog.Targets.FileTarget();
logfile.FileName = fileName + ".log";
logfile.KeepFileOpen = true;
logfile.Initialize();
var rule = new NLog.Config.LoggingRule("*", logfile);
NLog.LogManager.Configuration.LoggingRules.Add(rule);
NLog.LogManager.ReconfigExistingLoggers();
//
// Proceed with converting file
//
logfile.Flush();
NLog.LogManager.Configuration.LoggingRules.Remove(rule);
NLog.LogManager.ReconfigExistingLoggers();

But no log file was created.

What did I wrong? Any idea?

MartinStettner
  • 28,719
  • 15
  • 79
  • 106

1 Answers1

64

The second post on this thread led me to the solution: http://nlog-project.org/forum.html#nabble-td1685349

You have to get the current NLog configuration, make changes to this LoggingConfiguration object, then assign it back to LogManager.Configuration.

This is the code I used:

LoggingConfiguration config = LogManager.Configuration;

var logFile = new FileTarget();
config.AddTarget("file", logFile);

logFile.FileName = fileName + ".log";
logFile.Layout = "${date} | ${message}";

var rule = new LoggingRule("*", LogLevel.Info, logFile);
config.LoggingRules.Add(rule);

LogManager.Configuration = config;

logger.Info("File converted!");
matthughes404
  • 2,427
  • 1
  • 20
  • 9
  • 10
    The line with the reassignment is very important: LogManager.Configuration = config; – habakuk May 04 '11 at 10:14
  • 4
    To clarify **The line with the reassignment is very important: LogManager.Configuration = config;** This is true because of the way NLog has written the getters and setters for the Configuration property. It's not pretty, but it has to be set again with a changed object; you can't change the property directly. – zshift Apr 18 '14 at 14:01
  • I had to reassign the logger variable at the end to get this to work: logger = LogManager.GetCurrentClassLogger(); – Aidan Jul 27 '16 at 11:05
  • 2
    very clear solution, thanks. I prefer giving filename directly to FileTarget. `string filename = string.Format("C:\\LogFile-{0:yyyy-MM-dd_hh-mm-ss-tt}", DateTime.Now); var logFile = new FileTarget(filename); config.AddTarget(logFile);` could also be a shorter usage. – aozan88 Oct 02 '16 at 20:54
  • 6
    If you'd prefer cleaner c# code (e.g. avoid answering uncomfortable questions of why a class reference is being copied back onto itself to invoke a 'magic' property setter), then replace **LogManager.Configuration = config;** with **LogManager.ReconfigExistingLoggers();** – stoj Aug 21 '17 at 05:44
  • 2
    @aozan88 new FileTarget(filename) sets the name of the target, not the fileName. – Alex Fainshtein Feb 02 '18 at 22:43
  • @Alex Fainshtein wow, that was a very important one for me in order to add multiple file targets. If I don't set the name FileTargets with no name are replaced. – DankMemester 'Andrew Servania' Sep 18 '18 at 08:23