2006年10月27日金曜日

log4netの出力を動的に

 VS2005のClickOnceで配布するアプリでlog4netを使うと、相対パスで指定したログファイルが奥深くに埋もれてしまう。実行時に指定してやればユーザが指定した場所に書けるんじゃないかとググッってみたら、ヒントが見つかった。設定ファイルの大部分をlog4net.cfgという名前で書いておいて、ファイル名だけを実行時に指定したらいいんだな。

 この時、appenderのファイル名を

<appender name="RollingLogFileAppender"
type="log4net.Appender.RollingFileAppender">
<param name="File" value="nul" />

のようにnulにしておけば、log4net.Config.XmlConfigurator.Configureを呼んだ直後の初期状態でログファイルの生成を抑止できる(unixでlog4jなら/dev/nullか?)。nul以外のファイル名を指定しちゃうと、どこかに0バイトのログファイルが生成されてしまうので注意。この後で、ログ出力が有効の場合にのみファイル名を設定してやれば、必要な時だけログを出力することができる。

public MyScriptForm()
{
InitializeComponent();
Properties.Settings appsettings =
new Properties.Settings();
if (appsettings.WriteEnabled)
{
setLogLocation(appsettings.OutputPath);
}
else
{
setLogLocation(null);
}
}

private void setLogLocation(string outputPath)
{
log4net.Config.XmlConfigurator.Configure(
new System.IO.FileInfo("log4net.cfg"));
if (outputPath != null)
{
if (!File.Exists(outputPath))
{
Directory.CreateDirectory(outputPath);
}
log4net.Repository.Hierarchy.Hierarchy hier =
(log4net.Repository.Hierarchy.Hierarchy)
log4net.LogManager.GetRepository();
if (hier != null)
{
log4net.Appender.FileAppender appender;
appender =
(log4net.Appender.FileAppender)
hier.GetLogger("MyScript",
hier.LoggerFactory).GetAppender(
"DebugLogFileAppender");
if (appender != null)
{
appender.File = outputPath +
Path.DirectorySeparatorChar + "debug.log";
appender.ActivateOptions();
}
}
}
...