答えは、Enterprise Library がデフォルトで exe の構成ファイルを使用することです。COM を含む dll を作成している場合、正当な理由により、呼び出し元の実行可能ファイルに依存したくない場合があります。これに対する 1 つの解決策 (他にもあるかもしれません) は、デフォルトのものを使用する代わりにエンタープライズ ライブラリ オブジェクトを自分で作成し、構成の取得元を指定することです。これは見かけほど怖くはなく、entlib などを再コンパイルする必要もありません。
単純に Logger.Write() を使用する代わりに、次のことを行いました: a) dll の構成ファイルを使用して、ログ ライターを作成します。
string dllConfigFilename = Assembly.GetExecutingAssembly().Location + ".config";
FileConfigurationSource exceptionsSource = new FileConfigurationSource(dllConfigFilename);
LogWriterFactory writerFactory = new LogWriterFactory(exceptionsSource);
logWriter = writerFactory.Create();
b) 次に、コード内でこのログ ライターを使用します。
LogEntry log = new LogEntry();
log.Message = message;
log.Categories = new string[] { "General" };
logWriter.Write(log);
私が作成したサンプル オブジェクトの完全なコードを次に示します。参照は、Microsoft.Practices.EnterpriseLibrary.Common、Microsoft.Practices.EnterpriseLibrary.Logging、Microsoft.Practices.ObjectBuilder、System、System.Data、System.Windows.Forms、System.Xml でした。
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Reflection;
using System.IO;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
namespace COMThing
{
[ComVisible(true)]
public class MyComThing : MyComInterface
{
LogWriter logWriter;
public MyComThing()
{
string dllConfigFilename = Assembly.GetExecutingAssembly().Location + ".config";
FileConfigurationSource exceptionsSource = new FileConfigurationSource(dllConfigFilename);
LogWriterFactory writerFactory = new LogWriterFactory(exceptionsSource);
logWriter = writerFactory.Create();
}
public bool ProcessMessage(string message)
{
LogEntry log = new LogEntry();
log.Message = message;
log.Categories = new string[] { "General" };
logWriter.Write(log);
MessageBox.Show(message);
return true;
}
}
}
プロジェクトには、「出力ディレクトリにコピー」を「常にコピー」に設定した COMThing.dll.config ファイルが含まれていました。これは、アプリケーション イベント ログにログ情報を書き込む単純な構成です。構成ファイルの内容は次のとおりです。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</configSections>
<loggingConfiguration name="Logging Application Block" tracingEnabled="true"
defaultCategory="General" logWarningsWhenNoCategoriesMatch="true">
<listeners>
<add source="COMThing Logger" formatter="Text Formatter" log="Application"
machineName="" listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FormattedEventLogTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
traceOutputOptions="None" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FormattedEventLogTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
name="Formatted EventLog TraceListener" />
</listeners>
<formatters>
<add template="Timestamp: {timestamp}
Message: {message}
Category: {category}
Priority: {priority}
EventId: {eventid}
Severity: {severity}
Title:{title}
Machine: {machine}
Application Domain: {appDomain}
Process Id: {processId}
Process Name: {processName}
Win32 Thread Id: {win32ThreadId}
Thread Name: {threadName}
Extended Properties: {dictionary({key} - {value}
)}"
type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
name="Text Formatter" />
</formatters>
<categorySources>
<add switchValue="All" name="General">
<listeners>
<add name="Formatted EventLog TraceListener" />
</listeners>
</add>
</categorySources>
<specialSources>
<allEvents switchValue="All" name="All Events">
<listeners>
<add name="Formatted EventLog TraceListener" />
</listeners>
</allEvents>
<notProcessed switchValue="All" name="Unprocessed Category" />
<errors switchValue="All" name="Logging Errors & Warnings">
<listeners>
<add name="Formatted EventLog TraceListener" />
</listeners>
</errors>
</specialSources>
</loggingConfiguration>
</configuration>
ビルドの下のプロジェクト プロパティで、[COM 相互運用に登録] をオンにします。プロジェクトをビルドし、次の .vbs ファイルを作成します。
Set obj = CreateObject("COMThing.MyComThing")
obj.ProcessMessage("called from com by vbs")
この vbs ファイルをダブルクリックすると、「called from com by vbs」というテキストを含むメッセージ ボックスが表示され、アプリケーション イベント ログにエントリが書き込まれます。これは、実行中のプロセスが C:\WINDOWS\System32\WScript.exe (または同様のもの) であるときに、dll の構成ファイルから構成を取得していることを示しています。
これは、 「複数の ConfigurationSource を使用する」の下の情報に基づいています。
Logger クラスには、さまざまな引数を持つ便利なヘルパー メソッドが多数含まれていることに注意してください。LogWriter クラスを使用しているため、この魔法は利用できません。個人的には、Logger に基づいて、ライブラリ内に同じジョブを実行する別のクラスを作成します。
参照されている記事では、データベースおよび例外アプリケーション ブロックに適用される同じ原則が示されています。おそらく、それらのほとんど/すべてに同じモデルを適用できます。