LoginSignup
3
8

More than 1 year has passed since last update.

WPF(C#) .NET6.0 で Log4net を実装 

Last updated at Posted at 2022-04-06

前回までで、ざっとWPF アプリを作成したので、今回は Log4net を実装します。

Log4net インストール

NuGet パッケージマネージャーで Log4net を取得します。
1.NuGET_Log4net.png

AssemblyInfo.cs に Log4net の定義を追加

AssemblyInfo.cs ファイルがない場合は追加しましょう。
[SampleWPF]プロジェクトを右クリック⇒[追加...]⇒[アセンブリ構成ファイル]

  • 設定ファイルのパスを指定する。ここではプロジェクト直下の log4net.xmlと指定。
AssemblyInfo.cs
using System.Windows;

[assembly: ThemeInfo(
    ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
                                     //(used if a resource is not found in the page,
                                     // or application resource dictionaries)
    ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
                                              //(used if a resource is not found in the page,
                                              // app, or any theme specific resource dictionaries)
)]

[assembly: log4net.Config.XmlConfigurator(ConfigFile = @"log4net.xml", Watch = true)]

Log4net 設定ファイルを作成

  • log4net.config.xml ファイルを追加する
    [SampleWPF]プロジェクトを右クリック⇒[追加...]⇒[XML ファイル]
    2.Log4net_config.png
    以下、ログレベルによる出力ファイルを切り分ける設定のサンプルです。
log4net.xml
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<log4net>
		<!-- Appender 設定 -->
		<!-- DEBUG level -->
		<appender name="DebugAppender" type="log4net.Appender.RollingFileAppender">
			<param name="File" value=".\logs\DEBUG" />
			<param name="AppendToFile" value="true" />
			<param name="RollingStyle" value="Date" />
			<param name="StaticLogFileName" value="false" />
			<param name="DatePattern" value="_yyyyMMdd'.log'" />
			<layout type="log4net.Layout.PatternLayout">
				<param name="ConversionPattern" value="%date{ISO8601} [%-5level] %message%n" />
			</layout>
			<filter type="log4net.Filter.LevelRangeFilter">
				<levelMin value="DEBUG" />
				<levelMax value="DEBUG" />
			</filter>
		</appender>

		<!-- INFO/WARN level -->
		<appender name="InfoWarnAppender" type="log4net.Appender.RollingFileAppender">
			<param name="File" value=".\logs\INFO" />
			<param name="AppendToFile" value="true" />
			<param name="RollingStyle" value="Date" />
			<param name="StaticLogFileName" value="false" />
			<param name="DatePattern" value="_yyyyMMdd'.log'" />
			<layout type="log4net.Layout.PatternLayout">
				<param name="ConversionPattern" value="%date{ISO8601} [%-5level] %message%n" />
			</layout>
			<filter type="log4net.Filter.LevelRangeFilter">
				<levelMin value="INFO" />
				<levelMax value="WARN" />
			</filter>
		</appender>

		<!-- ERROR/FATAL level -->
		<appender name="ErrorFatalAppender" type="log4net.Appender.RollingFileAppender">
			<param name="File" value=".\logs\ERROR" />
			<param name="AppendToFile" value="true" />
			<param name="RollingStyle" value="Date" />
			<param name="StaticLogFileName" value="false" />
			<param name="DatePattern" value="_yyyyMMdd'.log'" />
			<layout type="log4net.Layout.PatternLayout">
				<param name="ConversionPattern" value="%date{ISO8601} [%-5level] %message%n" />
			</layout>
			<filter type="log4net.Filter.LevelRangeFilter">
				<levelMin value="ERROR" />
				<levelMax value="FATAL" />
			</filter>
		</appender>

		<!-- Appender 指定 -->
		<root>
			<level value="DEBUG" />
			<appender-ref ref="DebugAppender" />
			<appender-ref ref="InfoWarnAppender" />
			<appender-ref ref="ErrorFatalAppender" />
		</root>

	</log4net>
</configuration>
  • ビルド時にlog4net.xmlを出力するように、プロパティの設定「出力ディレクトリにコピー」を「常にコピーする」に変更
    3.Build_Copy.png

MainWindowVM に実装してみる

  • Log4net.ILog を定義
 private static readonly log4net.ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
  • 「CS8603 null 参照の可能性」警告を抑制
#pragma warning disable CS8603
  • テストなので、MainWindowVM コンストラクタで確認
// Log4net テスト
logger.Debug("DEBUG level log");
logger.Info("INFO level log");
logger.Warn("WARN level log");
logger.Error("ERROR level log");
logger.Fatal("FATAL level log");

以下、MainWindowVM.cs のソースです。

ViewModels\MainWindowVM.cs
using SampleWPF.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace SampleWPF.ViewModels
{
    public class MainWindowVM    {

#pragma warning disable CS8602 // null 参照の可能性があるものの逆参照です。
        private static readonly log4net.ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
#pragma warning restore CS8602

        public static ObservableCollection<User>? userList { get; set; }
        public ObservableCollection<User> UserList
        {
#pragma warning disable CS8603 // Null 参照戻り値である可能性があります。
            get => userList;
#pragma warning restore CS8603
            set
            {
                userList = value;
            }
        }

        // Insert用データ
        private string insertFirstName;
        public string InsertFirstName
        {
            get => insertFirstName;
            set
            {
                insertFirstName = value;
            }
        }
        private string insertLastName;
        public string InsertLastName
        {
            get => insertLastName;
            set
            {
                insertLastName = value;
            }
        }

        private void UpdateUserList()
        {
            using (var dbcx = new SampleDbContext())
            {
                UserList.Clear();
                ObservableCollection<User> uList = new ObservableCollection<User>(dbcx.Users.ToList());
                foreach (var user in uList) this.UserList.Add(user);
            }

        }

        // DelegateCommand
        public ICommand InsertCommand { get; private set; }
        public void ExecuteInsert()
        {
            using (var dbcx = new SampleDbContext())
            {
                // LocalDB 更新
                User insertUser = new()
                {
                    // Id は LocalDB で自動的に付与される
                    FirstName = InsertFirstName,
                    LastName = InsertLastName
                };
                dbcx.Users.Add(insertUser);
                dbcx.SaveChanges();
            }
            UpdateUserList();

        }

        public ICommand ListTrashCommand { get; private set; }
        public void ExecuteTrash(int id)
        {
            using (var dbcx = new SampleDbContext())
            {
                // LocalDB 更新
                var user = dbcx.Users.Single(x => x.Id == id);
                dbcx.Users.Remove(user);

                dbcx.SaveChanges();
            }
            UpdateUserList();
        }

        public MainWindowVM()
        {
            UserList = new ObservableCollection<User>();

            InsertCommand = new ForwardedCommand(ExecuteInsert);
            ListTrashCommand = new ForwardedCommand<int>(ExecuteTrash);

            // CS8618 対応
            insertFirstName = "";
            insertLastName = "";

            // UserList 初期化
            UpdateUserList();

            // Log4net テスト
            logger.Debug("DEBUG level log");
            logger.Info("INFO level log");
            logger.Warn("WARN level log");
            logger.Error("ERROR level log");
            logger.Fatal("FATAL level log");
        }

    }
}

実行してログを確認

  • 実行ファイルフォルダの logs フォルダに以下のファイルが作成されるはず
    4.Log4net_output.png
  • ログ内容
DEBUG_20220405.log
2022-04-05 22:24:04,732 [DEBUG] DEBUG level log
ERROR_20220405.log
2022-04-05 22:24:04,741 [ERROR] ERROR level log
2022-04-05 22:24:04,741 [FATAL] FATAL level log
INFO_20220405.log
2022-04-05 22:24:04,740 [INFO ] INFO level log
2022-04-05 22:24:04,741 [WARN ] WARN level log

以上で、Log4net の実装を完了します。

次回予告

次回は、一通りアプリっぽくなったので、WiX を使って Windows Installer を作成する予定です。

3
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
8