简体   繁体   中英

How to configure log4net with VSTO project in visual studio

I was trying to build a simple outlook add in. I created a VSTO project in Visual Studio 2017 .

When the project is created by the Visual Studio, there is no app.config or web.config in the solution. I want to use log4net for this project. How should I configure it? I tried to add web.config or app.config for the project. But I was not able to get values from the configure file. I think the project cannot recognize them. I cannot use ConfigurationManager.AppSettings["key"] to get the value from the configure file.

Does anyone know how to use log4net in VSTO project?

Thank you.

Install Log4Net through the NuGet Package Manager. Then create a setting in the project properties, like asdf (you can delete the setting after you update the app.config file with the Log4Net sections), it will then create the app.config for you.

屏幕截图

Here's the configuration in app.config for Log4Net I use on most of my projects. I created a new project with a setting asdf and added my standard Log4Net setup.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="ExcelAddIn1.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
        </sectionGroup>
      <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
    </configSections>
    <userSettings>
        <ExcelAddIn1.Properties.Settings>
            <setting name="asdf" serializeAs="String">
                <value>asdf</value>
            </setting>
        </ExcelAddIn1.Properties.Settings>
    </userSettings>
    <log4net>
        <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
            <layout type="log4net.Layout.PatternLayout">
                <conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline"/>
            </layout>
        </appender>
        <appender name="FileAppender" type="log4net.Appender.FileAppender">
            <file value="C:\Temp\MyOfficeAddIn.log"/>
            <appendToFile value="true"/>
            <lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
            <layout type="log4net.Layout.PatternLayout">
                <conversionPattern value="%date|%-5level|%message%newline"/>
            </layout>
        </appender>
        <root>
            <level value="ALL"/>
            <appender-ref ref="FileAppender"/>
        </root>
    </log4net>
</configuration>

I usually create a class called ErrorHandler and add the following code.

using System;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Excel = Microsoft.Office.Interop.Excel;
using log4net;
using log4net.Config;

[assembly: log4net.Config.XmlConfigurator(Watch = true)]

Then I use the following methods to write to the log file

    private static readonly ILog log = LogManager.GetLogger(typeof(ErrorHandler));

    /// <summary>
    /// Applies a new path for the log file by FileAppender name
    /// </summary>
    public static void SetLogPath()
    {
        XmlConfigurator.Configure();
        log4net.Repository.Hierarchy.Hierarchy h = (log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository();
        string logFileName = System.IO.Path.Combine(Properties.Settings.Default.App_PathLocalData, AssemblyInfo.Product + ".log");

        foreach (var a in h.Root.Appenders)
        {
            if (a is log4net.Appender.FileAppender)
            {
                if (a.Name.Equals("FileAppender"))
                {
                    log4net.Appender.FileAppender fa = (log4net.Appender.FileAppender)a;
                    fa.File = logFileName;
                    fa.ActivateOptions();
                }
            }
        }
    }

    /// <summary>
    /// Create a log record to track which methods are being used.
    /// </summary>
    public static void CreateLogRecord()
    {
        try
        {
            // gather context
            var sf = new System.Diagnostics.StackFrame(1);
            var caller = sf.GetMethod();
            var currentProcedure = caller.Name.Trim();

            // handle log record
            var logMessage = string.Concat(new Dictionary<string, string>
            {
                ["PROCEDURE"] = currentProcedure,
                ["USER NAME"] = Environment.UserName,
                ["MACHINE NAME"] = Environment.MachineName
            }.Select(x => $"[{x.Key}]=|{x.Value}|"));
            log.Info(logMessage);

        }
        catch (Exception ex)
        {
            ErrorHandler.DisplayMessage(ex);

        }
    }

    /// <summary> 
    /// Used to produce an error message and create a log record
    /// <example>
    /// <code lang="C#">
    /// ErrorHandler.DisplayMessage(ex);
    /// </code>
    /// </example> 
    /// </summary>
    /// <param name="ex">Represents errors that occur during application execution.</param>
    /// <param name="isSilent">Used to show a message to the user and log an error record or just log a record.</param>
    /// <remarks></remarks>
    public static void DisplayMessage(Exception ex, Boolean isSilent = false)
    {
        // gather context
        var sf = new System.Diagnostics.StackFrame(1);
        var caller = sf.GetMethod();
        var errorDescription = ex.ToString().Replace("\r\n", " "); // the carriage returns were messing up my log file
        var currentProcedure = caller.Name.Trim();
        var currentFileName = AssemblyInfo.GetCurrentFileName();

        // handle log record
        var logMessage = string.Concat(new Dictionary<string, string>
        {
            ["PROCEDURE"] = currentProcedure,
            ["USER NAME"] = Environment.UserName,
            ["MACHINE NAME"] = Environment.MachineName,
            ["FILE NAME"] = currentFileName,
            ["DESCRIPTION"] = errorDescription,
        }.Select(x => $"[{x.Key}]=|{x.Value}|"));
        log.Error(logMessage);

        // format message
        var userMessage = new StringBuilder()
            .AppendLine("Contact your system administrator. A record has been created in the log file.")
            .AppendLine("Procedure: " + currentProcedure)
            .AppendLine("Description: " + errorDescription)
            .ToString();

        // handle message
        if (isSilent == false)
        {
            MessageBox.Show(userMessage, "Unexpected Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

I have a project in GitHub you can use as an example .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM