Search code examples
c#outlookadd-innlog

NLog does not write to log file when called from Outlook Add-in


I have a C# Add-in for Outlook (Add-In Express) from which I'm trying to store some log data, but no log file is created even though the calls to logger do not fail. I am using VS 2013 in a Win 10 environment.

My NLog.Config file (stored in folder OutlookAddin\bin\Debug, the same location as OutlookAddIn.dll.config) is as follows:

<?xml version="1.0" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
    <target name="file" xsi:type="File"
        layout="${longdate} ${logger} ${message}" 
        fileName="${specialfolder:ApplicationData}\FindAlike\NewMails.txt"
        keepFileOpen="false"
        encoding="iso-8859-2" />
</targets>

<rules>
    <logger name="*"  writeTo="file" />
</rules>

Code within the Add-In is declaration:

public AddinModule()
    {
        Application.EnableVisualStyles();
        InitializeComponent();
        // Please add any initialization code to the AddinInitialize event handler
    }

    private ADXOutlookAppEvents adxOutlookEvents;
    private DateTime LastReceivedDate = DateTime.Now;
    private Timer mailCheckTimer;
    public static RegistryKey SoftwareKey = Registry.CurrentUser.OpenSubKey("Software", true);
    public static RegistryKey AppNameKey = SoftwareKey.CreateSubKey("FindAlike");
    public static Logger logger = LogManager.GetCurrentClassLogger();

And routine for testing log file writing is:

public static void TestNLog()
    {
        try
        {
            NLog.LogManager.ThrowExceptions = true;

            logger.Info("test1");
            logger.Warn("test2");
            logger.Error("test3");

            var fileTarget1 = (FileTarget)NLog.LogManager.Configuration.FindTargetByName("file");
            var logEventInfo = new LogEventInfo { TimeStamp = DateTime.Now };
            string fileName = fileTarget1.FileName.Render(logEventInfo);
            if (!System.IO.File.Exists(fileName))
                throw new Exception("Log file does not exist.");
        }
        catch (Exception Ex)
        {
            MessageBox.Show(Ex.Message);
        }
    }

When TestNLog is called, the Message that the log file does not exist appears, although the target file is correct, indicating that the config file has been successfully read.

The same code works as expected when included in an executable.


Solution

  • In addition to @SimonKarvis's answer, the location of the nlog.config could be difficult. This is the same for unit tests.

    I would recommend:

    1. Creating the config from C#, e.g.

       var target = new FileTarget
       {
             FileName = logfile,
             ReplaceFileContentsOnEachWrite = true,
             CreateDirs = createDirs
       };
       var config = new LoggingConfiguration();
      
       config.AddTarget("logfile", target);
      
       config.AddRuleForAllLevels(target);
      
       LogManager.Configuration = config;
      
    2. Or load the config from a string:

      string configXml = "<nlog>...<nlog>";
      XmlDocument doc = new XmlDocument();
      doc.LoadXml(configXml);
      var config = new XmlLoggingConfiguration(doc.DocumentElement, Environment.CurrentDirectory);
      LogManager.Configuration = config;
      
    3. Or least but not last, find the correct path of nlog.config and "feed" it to NLog.

      var pathToNlogConfig = "c:\..";
      var config = new XmlLoggingConfiguration(pathToNlogConfig);
      LogManager.Configuration = config;