1

我正在尝试将.net 代码中的 EntLib 3.1 用于为 COM 互操作注册的 dll。我在哪里放置配置文件?

或者,有没有办法在 dll 代码中指定它应该从哪里获取 entlib 配置?由于我的 dll 将从 COM 调用,所以我并不总是知道什么 exe 会调用它。

我创建了一个使用 entlib Logging 的简单应用程序,它有两个类:“CallingApp”和“MyComThing”。当我从 CallingApp 调用 MyComThing 的方法时,它会使用 CallingApp 的配置文件中的配置进行记录。当我从 vbs 脚本(即通过 COM)调用 MyComThing 的方法时,出现错误“在配置源中找不到 Logging 的配置部分”。我的 COMThing.dll.config 文件与注册的 COMThing.dll 位于同一文件夹中,即 bin\debug\ 文件夹中。

谢谢!

4

2 回答 2

3

答案是企业库默认使用 exe 的配置文件。如果您正在生成一个 dll,包括 COM,那么出于充分的理由,您可能不想依赖调用可执行文件。对此的一种解决方案(可能还有其他解决方案)是自己创建企业库对象而不是使用默认对象,并告诉他们从哪里获取配置。这并不像看起来那么可怕,并且不需要重新编译 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}&#xD;&#xA;Message: {message}&#xD;&#xA;Category: {category}&#xD;&#xA;Priority: {priority}&#xD;&#xA;EventId: {eventid}&#xD;&#xA;Severity: {severity}&#xD;&#xA;Title:{title}&#xD;&#xA;Machine: {machine}&#xD;&#xA;Application Domain: {appDomain}&#xD;&#xA;Process Id: {processId}&#xD;&#xA;Process Name: {processName}&#xD;&#xA;Win32 Thread Id: {win32ThreadId}&#xD;&#xA;Thread Name: {threadName}&#xD;&#xA;Extended Properties: {dictionary({key} - {value}&#xD;&#xA;)}"
        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 &amp; Warnings">
        <listeners>
          <add name="Formatted EventLog TraceListener" />
        </listeners>
      </errors>
    </specialSources>
  </loggingConfiguration>
</configuration>

在 Build 下的项目属性中,检查“Register for COM interop”。构建项目,然后创建以下 .vbs 文件:

Set obj = CreateObject("COMThing.MyComThing")
obj.ProcessMessage("called from com by vbs")

如果你双击这个 vbs 文件,它应该会显示一个带有文本“由 vbs 从 com 调用”的消息框,并在应用程序事件日志中写入一个条目。这表明,虽然执行过程是 C:\WINDOWS\System32\WScript.exe(或类似的),但它正在从您的 dll 的配置文件中获取配置。

我基于“使用多个配置源”下的信息。

请注意,Logger 类包含许多具有不同参数的好帮手方法。由于我们使用的是 LogWriter 类,因此我们无法获得这种魔力。就我个人而言,我将在我的库中创建另一个类来执行相同的工作,基于 Logger。

引用的文章显示了应用于数据库和异常应用程序块的相同原理。大概相同的模型可以应用于大多数/全部。

于 2008-12-11T18:07:33.407 回答
0

检查我遇到的相关问题。也许它有一些帮助。

如何在已发布的 .Net 站点上包含 COM 组件?

于 2008-12-11T13:47:19.643 回答