C# 如何在运行时使用 NLog 获取当前目标文件的路径?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11452645/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 17:54:32  来源:igfitidea点击:

How to get path of current target file using NLog in runtime?

c#nlog

提问by Win4ster

I use NLog with next configuration:

我在下一个配置中使用 NLog:

  <targets>
    <target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
            layout="${longdate} ${uppercase:${level}} ${message}" />
  </targets>
  <rules>
    <logger name="*" minlevel="Trace" writeTo="f" />
  </rules>

I tried to get FileNameproperty of FileTarget(I check, that there only one FileTarget in collection)

我试图获得的FileName属性FileTarget(我检查,集合中只有一个 FileTarget)

NLog.LogManager.GetCurrentClassLogger().Info("test");
var logFile = (from t in NLog.LogManager.Configuration.AllTargets
                where t is NLog.Targets.FileTarget
                select (NLog.Targets.FileTarget)t).FirstOrDefault();

But logFile.FileName contains only pattern of file name, exactly how it's specified in settings.

但是 logFile.FileName 只包含文件名的模式,正是它在设置中指定的方式。

How can I get in runtime path of current log file?

如何进入当前日志文件的运行时路径?

采纳答案by Mike

This did the trick for me:

这对我有用:

var fileTarget = (FileTarget) LogManager.Configuration.FindTargetByName("file");
// Need to set timestamp here if filename uses date. 
// For example - filename="${basedir}/logs/${shortdate}/trace.log"
var logEventInfo = new LogEventInfo {TimeStamp = DateTime.Now}; 
string fileName = fileTarget.FileName.Render(logEventInfo);
if (!File.Exists(fileName))
    throw new Exception("Log file does not exist.");

回答by markmuetz

This method will work even if you have set async="true"(i.e. your target is wrapped by an AsyncTargetWrapper) in your NLog XML configuration:

即使您已在 NLog XML 配置中设置async="true"(即您的目标由 包装AsyncTargetWrapper),此方法也将起作用:

    private string GetLogFileName(string targetName)
    {
        string fileName = null;

        if (LogManager.Configuration != null && LogManager.Configuration.ConfiguredNamedTargets.Count != 0)
        {
            Target target = LogManager.Configuration.FindTargetByName(targetName);
            if (target == null)
            {
                throw new Exception("Could not find target named: " + targetName);
            }

            FileTarget fileTarget = null;
            WrapperTargetBase wrapperTarget = target as WrapperTargetBase;

            // Unwrap the target if necessary.
            if (wrapperTarget == null)
            {
                fileTarget = target as FileTarget;
            }
            else
            {
                fileTarget = wrapperTarget.WrappedTarget as FileTarget;
            }

            if (fileTarget == null)
            {
                throw new Exception("Could not get a FileTarget from " + target.GetType());
            }

            var logEventInfo = new LogEventInfo { TimeStamp = DateTime.Now };
            fileName = fileTarget.FileName.Render(logEventInfo);
        }
        else
        {
            throw new Exception("LogManager contains no Configuration or there are no named targets");
        }

        if (!File.Exists(fileName))
        {
            throw new Exception("File " + fileName + " does not exist");
        }

        return fileName;
    }

回答by Pawel Cioch

I know that my answer is not exactly answering the question, but the most difficult thing is to find the right target and cast it properly, then we can access any properties. I also didn't find a question that would fit my answer thus posting here...

我知道我的回答并没有完全回答问题,但最困难的是找到正确的目标并正确施放,然后我们可以访问任何属性。我也没有找到适合我的答案的问题,因此张贴在这里......

This method will work even if you have set async="true"(i.e. your target is wrapped by an AsyncTargetWrapperor any TargetWrapper) in your NLog XML configuration:

即使您已在 NLog XML 配置中设置async="true"(即您的目标由一个AsyncTargetWrapper或任何 TargetWrapper 包装),此方法也将起作用:

Using NLog Version: 3.1.0.0

使用 NLog 版本:3.1.0.0

Runtime Version: v4.0.30319

运行时版本:v4.0.30319

    private Target FindTargetByName(string targetName)
    {
        if (LogManager.Configuration == null)
            return null;

        Target t = LogManager.Configuration.FindTargetByName(targetName);

        if (t is NLog.Targets.Wrappers.WrapperTargetBase)
        {
            var list = LogManager.Configuration.AllTargets.ToList();
            t = list.Find(x => x.Name == targetName + "_wrapped");
            return t;
        }
        else
        {
            return t;
        }
    }

Usage for MailTarget named emailError

名为 emailError 的 MailTarget 的用法

var emailError = (MailTarget)FindTargetByName("emailError");
emailError.SmtpServer = "" //you can set or get

回答by Skip

Targets can be wrapped multiple times (in my case I had a filter), so the following snippet is a more generic approach to unwrapping that works for multiple levels and doesn't make assumptions about target names.

目标可以被包装多次(在我的例子中我有一个过滤器),所以下面的代码片段是一种更通用的解包方法,适用于多个级别,并且不对目标名称做出假设。

Target target = LogManager.Configuration.FindTargetByName(targetName);
while ((target != null) && (target is WrapperTargetBase))
{
    target = (target as WrapperTargetBase).WrappedTarget;
}