8

免 NLog.config 設定 Log 路徑

 3 years ago
source link: https://blog.darkthread.net/blog/config-nlog-by-code/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

免 NLog.config 設定 Log 路徑

calendar.svg 2021-01-23 07:11 AM comment.svg 2 eye.svg 1,512

最近用 C# 寫了幾支小工具要交給 End-User 桌面執行,為簡化部署程序,將參照 DLL 併入整成單一 EXE 檔是我愛用的做法。

免安裝,不必解壓一堆 EXE、DLL 存到特定資料夾,整個工具就一個 EXE 檔,放到桌面上點兩下便能用,很棒吧!

.NET Core 3 支援編譯封裝成單一執行檔 (參考:封裝 .NET Core 應用程式成單一可執行檔並優化檔案大小 by Poy Change),執行時再將內嵌的 DLL 存放在暫存資料夾使用。去年底發佈的 .NET 5 則更上層樓,做到真正的單一 EXE 檔執行,不再需要將參照 DLL 寫成實體暫存檔。

雖已看到美好未來,但手邊這幾個工具仍是用 .NET Framework 開發。在 .NET Framework 實現單檔部署,我優先想到的是 MSBUild.ILMerge.Task,但我的 Console Apllcation 用到 SharePoint CSOM 不幸踩到 CSOM 跟 ILMerge 不相容的雷,靠著改用自動內嵌參照 DLL + AppDomain.CurrentDomain.AssemblyResolve 大絕才解決。

剩下一個小問題 - 程式有用 NLog 記錄執行歷程以備偵錯,一般需要有 NLog.config 定義存 Log 的路徑。都說要追求單一執行檔了,留個 NLog.config 小尾巴有點阿雜。另一方面,若使用者將程式放在桌面,NLog.config 及 Log 目錄跟 EXE 一起出現在桌面也不太優。經評估,用程式動態指定 Log 目錄是較完美的做法,一方面不用多產生 NLog.config,再則可以視情況動態修正 - 預設將 Log 存在 EXE 同路徑的 MyToolLogs 資料夾;若 EXE 被放在桌面,就改存在 TEMP 下的 MyToolLogs 資料夾以免有礙觀瞻。

強大的 NLog 支援以程式碼設定路徑,讓我們能輕鬆完成任務,下面是程式範例:

using NLog;
using NLog.Targets;
using System;
using System.IO;
using System.Reflection;

namespace MyTool
{
    class Program
    {
        //透過程式設定 NLog 時,要留意 statci logger 取得物件時機
        //要排在 SetupNLog() 之後
        static ILogger logger = null;
        
        static void SetupNLog()
        {
            var config = new NLog.Config.LoggingConfiguration();
            //偵測程式是不是被放在桌面
            var onDesktop =
                Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ==
                Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
            var logFile = new NLog.Targets.FileTarget("f") { 
                FileName = 
                    (onDesktop ? Path.GetTempPath() : "${basedir}") +
                    "/MyToolLogs/${shortdate}.log" 
            };
            config.AddRule(LogLevel.Trace, LogLevel.Fatal, logFile);
            LogManager.Configuration = config;
            logger = NLog.LogManager.GetLogger("debug");
        }

        static void Main(string[] args)
        {
            //趕在引用 NLog 程式庫前完成設定
            SetupNLog();

            //檢查 Log 路徑並列印出來
            //REF: https://blog.darkthread.net/blog/get-nlog-path/
            Console.WriteLine(
                (LogManager.Configuration.FindTargetByName("f") as FileTarget).FileName
                .Render(new LogEventInfo() { 
                    TimeStamp = DateTime.Now, LoggerName = "loggerName" 
                }));

            logger.Debug("Hi there.");
            Console.ReadLine();
        }
    }
}

測試成功!

and has 2 comments

Comments

Post a comment

Comment
Name Captcha 50 + 23 =

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK