在调试模式下将Visual Studio用于Excel VSTO插件时,我无法加载log4net.config文件。配置文件位于我的项目的顶级目录中。我将“复制到输出目录”属性设置为“始终复制”。这样可以确保将文件复制到bin / Debug / log4net.config。我可以在构建时验证这种情况。
但是,当我在调试模式下运行时,该文件将不会加载。我放弃了尝试使文件自动加载的决定,并决定按照this question底部的OP代码,通过代码进行操作。
但是,我意识到我需要使用配置文件的绝对路径,因为相对路径没有被使用。在further investigation上,我意识到正在执行的DLL实际上不是debug / bin文件夹中的DLL。它在以下位置:
C:\Users\cbhandal\AppData\Local\assembly\dl3\MO52QQWP.9ZL\K36XZHGN.1PB\230751e6\d09b7fb2_19f6d401
还将System.IO.Directory.GetCurrentDirectory();
找到的当前工作目录也设置为"C:\\Users\\cbhandal\\Documents"
。
将路径硬编码为绝对路径,如以下代码所示:
var log4netConfig = "C:\\" + path + "\\Log4net.config";
var log4netInfo = new FileInfo(log4netConfig);
log4net.Config.XmlConfigurator.ConfigureAndWatch(log4netInfo);
但是那不是我可以部署的解决方案。我被困在这里。想知道是否有一种方法可以强制Visual Studio将.config文件复制到该appdata / temp位置,或者是否有一种方法可以以编程方式引用原始DLL所在的文件夹-构建的文件夹。或者,如果有人有其他解决方案?
对我来说,最简单的解决方案是使用此方法:https://stackoverflow.com/a/6963420/4754981
但是该链接上还有其他针对不同方法的解决方案,每个都有其警告。
所以我看起来像这样:
using System.Reflection;
using System.IO;
using System;
public static class Extensions {
private static string GetDirectory(this Assembly a) {
string codeBase = a.CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
return Path.GetDirectoryName(path);
}
private static void AlterLogPath(this log4net.Repository.ILoggerRepository repo, string newPath, string directory="") {
log4net.Repository.Hierarchy.Hierarchy h = (log4net.Repository.Hierarchy.Hierarchy) repo;
foreach (log4net.Appender.IAppender a in h.Root.Appenders) {
if (a is log4net.Appender.FileAppender) {
var fa = (log4net.Appender.FileAppender)a;
var fileName = Path.GetFileName(fa.File);
fa.File = newPath + (String.IsNullOrEmpty(directory)?"":(directory + Path.DirectorySeparatorChar.ToString())) + fileName;
fa.ActivateOptions();
break;
}
}
}
}
并且在启动中(通过[assembly: System.Web.PreApplicationStartMethod]
或asp的其他方式),或主应用程序。
static void Main() {
var PATH = Assembly.GetExecutingAssembly().GetDirectory() + Path.DirectorySeparatorChar.ToString();
log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(PATH + "log4net.config"));
log4net.LogManager.GetRepository().AlterLogPath(PATH, "Logs");
}