log4net 不适用于 VS 2015 扩展
log4net not working with VS 2015 extension
我有一个 Visual Studio 2015 扩展,想使用 log4net。
但是,我没有收到任何日志消息,甚至没有来自 log4net 的内部调试消息。
在包裹 class 我有:
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
后来在 Initialize 方法中我有:
if (!log4net.LogManager.GetRepository().Configured)
{
log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo("C:\Program Files\Sym\bin\Log4NetSettingsGlobal.xml"));
}
log.Debug("Package Initialize");
在 VSX 项目的 app.config 我有这个:
<configuration>
<appSettings>
<add key="log4net.Internal.Debug" value="true"/>
</appSettings>
<system.diagnostics>
<trace autoflush="true">
<listeners>
<add name="textWriterTraceListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="C:\Program Files\Sym\Logging\Log4Net_Trace_VSX.txt"/>
</listeners>
</trace>
</system.diagnostics>
...
</configuration>
上面的文本文件没有写入任何内容。当我在 VS 中调试扩展时,没有任何内容写入输出 window,也就是说,打开了 VS 的第二个实例,以便我可以测试扩展。
我也添加了一个 DebugAppender from this SO question。输出中仍然没有任何内容 window.
我做错了什么?
根据您的描述,我使用 log4net 创建了一个简单的自定义命令 vsix 项目,没有更改 app.config 文件,它可以工作。
Log4Net.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<log4net>
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<!--log Path-->
<param name= "File" value= "F:\App_Log\"/>
<!--append log to file-->
<param name= "AppendToFile" value= "true"/>
<!--log keep days-->
<param name= "MaxSizeRollBackups" value= "10"/>
<param name= "StaticLogFileName" value= "false"/>
<!--log farmat:2008-08-31.log-->
<param name= "DatePattern" value= "yyyy-MM-dd".log""/>
<param name= "RollingStyle" value= "Date"/>
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" />
</layout>
</appender>
<appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
<mapping>
<level value="ERROR" />
<foreColor value="Red, HighIntensity" />
</mapping>
<mapping>
<level value="Info" />
<foreColor value="Green" />
</mapping>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%n%date{HH:mm:ss,fff} [%-5level] %m" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="Info" />
<param name="LevelMax" value="Fatal" />
</filter>
</appender>
<root>
<!--(high) OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL (low) -->
<level value="all" />
<appender-ref ref="ColoredConsoleAppender"/>
<appender-ref ref="RollingLogFileAppender"/>
</root>
</log4net>
</configuration>
使用 log4net 的自定义命令
using System;
using System.ComponentModel.Design;
using System.Globalization;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using log4net.Config;
using System.IO;
using log4net;
namespace CommandDemo
{
/// <summary>
/// Command handler
/// </summary>
internal sealed class FirstCommand
{
/// <summary>
/// Command ID.
/// </summary>
public const int CommandId = 0x0100;
/// <summary>
/// Command menu group (command set GUID).
/// </summary>
public static readonly Guid CommandSet = new Guid("30f5b2c4-9c7f-4748-a1de-d6d03fe40eda");
/// <summary>
/// VS Package that provides this command, not null.
/// </summary>
private readonly Package package;
private ILog logger;
/// <summary>
/// Initializes a new instance of the <see cref="FirstCommand"/> class.
/// Adds our command handlers for menu (commands must exist in the command table file)
/// </summary>
/// <param name="package">Owner package, not null.</param>
private FirstCommand(Package package)
{
InitLog4Net();
logger = LogManager.GetLogger(typeof(FirstCommand));
if (package == null)
{
throw new ArgumentNullException("package");
}
this.package = package;
OleMenuCommandService commandService = this.ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
if (commandService != null)
{
var menuCommandID = new CommandID(CommandSet, CommandId);
var menuItem = new MenuCommand(this.MenuItemCallback, menuCommandID);
commandService.AddCommand(menuItem);
}
}
/// <summary>
/// Gets the instance of the command.
/// </summary>
public static FirstCommand Instance
{
get;
private set;
}
/// <summary>
/// Gets the service provider from the owner package.
/// </summary>
private IServiceProvider ServiceProvider
{
get
{
return this.package;
}
}
/// <summary>
/// Initializes the singleton instance of the command.
/// </summary>
/// <param name="package">Owner package, not null.</param>
public static void Initialize(Package package)
{
Instance = new FirstCommand(package);
}
/// <summary>
/// This function is the callback used to execute the command when the menu item is clicked.
/// See the constructor to see how the menu item is associated with this function using
/// OleMenuCommandService service and MenuCommand class.
/// </summary>
/// <param name="sender">Event sender.</param>
/// <param name="e">Event args.</param>
private void MenuItemCallback(object sender, EventArgs e)
{
string message = string.Format(CultureInfo.CurrentCulture, "Inside {0}.MenuItemCallback()", this.GetType().FullName);
string title = "FirstCommand";
logger.Debug("DebugInfo");
//logger.Info("TestInfo");
//logger.Warn("Testwarning");
//logger.Error("Testexception");
//logger.Fatal("Testerror");
// Show a message box to prove we were here
VsShellUtilities.ShowMessageBox(
this.ServiceProvider,
message,
title,
OLEMSGICON.OLEMSGICON_INFO,
OLEMSGBUTTON.OLEMSGBUTTON_OK,
OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
}
private void InitLog4Net()
{
var logCfg = new FileInfo(@"C:\log4netconfigpath\log4net.config");
XmlConfigurator.Configure(logCfg);
}
}
}
我有一个 Visual Studio 2015 扩展,想使用 log4net。 但是,我没有收到任何日志消息,甚至没有来自 log4net 的内部调试消息。
在包裹 class 我有:
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
后来在 Initialize 方法中我有:
if (!log4net.LogManager.GetRepository().Configured)
{
log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo("C:\Program Files\Sym\bin\Log4NetSettingsGlobal.xml"));
}
log.Debug("Package Initialize");
在 VSX 项目的 app.config 我有这个:
<configuration>
<appSettings>
<add key="log4net.Internal.Debug" value="true"/>
</appSettings>
<system.diagnostics>
<trace autoflush="true">
<listeners>
<add name="textWriterTraceListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="C:\Program Files\Sym\Logging\Log4Net_Trace_VSX.txt"/>
</listeners>
</trace>
</system.diagnostics>
...
</configuration>
上面的文本文件没有写入任何内容。当我在 VS 中调试扩展时,没有任何内容写入输出 window,也就是说,打开了 VS 的第二个实例,以便我可以测试扩展。
我也添加了一个 DebugAppender from this SO question。输出中仍然没有任何内容 window.
我做错了什么?
根据您的描述,我使用 log4net 创建了一个简单的自定义命令 vsix 项目,没有更改 app.config 文件,它可以工作。
Log4Net.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<log4net>
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<!--log Path-->
<param name= "File" value= "F:\App_Log\"/>
<!--append log to file-->
<param name= "AppendToFile" value= "true"/>
<!--log keep days-->
<param name= "MaxSizeRollBackups" value= "10"/>
<param name= "StaticLogFileName" value= "false"/>
<!--log farmat:2008-08-31.log-->
<param name= "DatePattern" value= "yyyy-MM-dd".log""/>
<param name= "RollingStyle" value= "Date"/>
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" />
</layout>
</appender>
<appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
<mapping>
<level value="ERROR" />
<foreColor value="Red, HighIntensity" />
</mapping>
<mapping>
<level value="Info" />
<foreColor value="Green" />
</mapping>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%n%date{HH:mm:ss,fff} [%-5level] %m" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="Info" />
<param name="LevelMax" value="Fatal" />
</filter>
</appender>
<root>
<!--(high) OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL (low) -->
<level value="all" />
<appender-ref ref="ColoredConsoleAppender"/>
<appender-ref ref="RollingLogFileAppender"/>
</root>
</log4net>
</configuration>
使用 log4net 的自定义命令
using System;
using System.ComponentModel.Design;
using System.Globalization;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using log4net.Config;
using System.IO;
using log4net;
namespace CommandDemo
{
/// <summary>
/// Command handler
/// </summary>
internal sealed class FirstCommand
{
/// <summary>
/// Command ID.
/// </summary>
public const int CommandId = 0x0100;
/// <summary>
/// Command menu group (command set GUID).
/// </summary>
public static readonly Guid CommandSet = new Guid("30f5b2c4-9c7f-4748-a1de-d6d03fe40eda");
/// <summary>
/// VS Package that provides this command, not null.
/// </summary>
private readonly Package package;
private ILog logger;
/// <summary>
/// Initializes a new instance of the <see cref="FirstCommand"/> class.
/// Adds our command handlers for menu (commands must exist in the command table file)
/// </summary>
/// <param name="package">Owner package, not null.</param>
private FirstCommand(Package package)
{
InitLog4Net();
logger = LogManager.GetLogger(typeof(FirstCommand));
if (package == null)
{
throw new ArgumentNullException("package");
}
this.package = package;
OleMenuCommandService commandService = this.ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
if (commandService != null)
{
var menuCommandID = new CommandID(CommandSet, CommandId);
var menuItem = new MenuCommand(this.MenuItemCallback, menuCommandID);
commandService.AddCommand(menuItem);
}
}
/// <summary>
/// Gets the instance of the command.
/// </summary>
public static FirstCommand Instance
{
get;
private set;
}
/// <summary>
/// Gets the service provider from the owner package.
/// </summary>
private IServiceProvider ServiceProvider
{
get
{
return this.package;
}
}
/// <summary>
/// Initializes the singleton instance of the command.
/// </summary>
/// <param name="package">Owner package, not null.</param>
public static void Initialize(Package package)
{
Instance = new FirstCommand(package);
}
/// <summary>
/// This function is the callback used to execute the command when the menu item is clicked.
/// See the constructor to see how the menu item is associated with this function using
/// OleMenuCommandService service and MenuCommand class.
/// </summary>
/// <param name="sender">Event sender.</param>
/// <param name="e">Event args.</param>
private void MenuItemCallback(object sender, EventArgs e)
{
string message = string.Format(CultureInfo.CurrentCulture, "Inside {0}.MenuItemCallback()", this.GetType().FullName);
string title = "FirstCommand";
logger.Debug("DebugInfo");
//logger.Info("TestInfo");
//logger.Warn("Testwarning");
//logger.Error("Testexception");
//logger.Fatal("Testerror");
// Show a message box to prove we were here
VsShellUtilities.ShowMessageBox(
this.ServiceProvider,
message,
title,
OLEMSGICON.OLEMSGICON_INFO,
OLEMSGBUTTON.OLEMSGBUTTON_OK,
OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
}
private void InitLog4Net()
{
var logCfg = new FileInfo(@"C:\log4netconfigpath\log4net.config");
XmlConfigurator.Configure(logCfg);
}
}
}