Entlib和interop:它是否有效,配置文件在哪里?

时间:2022-05-29 08:06:17

I'm trying to use the EntLib 3.1 within .net code for a dll which is registered for COM interop. Where do I put the config file?

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

Alternatively, is there a way to specify within the dll code where it should get the entlib config from? Since my dll will be called from COM I don't always know what exe will be calling it.

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

I created a simple app which uses entlib Logging, with two classes: 'CallingApp' and 'MyComThing'. When I call a method of MyComThing from CallingApp it logs using the configuration in CallingApp's config file. When I call the method of MyComThing from a vbs script, ie through COM, I get an error "The configuration section for Logging cannot be found in the configuration source". My COMThing.dll.config file is in the same folder as the registered COMThing.dll, ie in the bin\debug\ folder.

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

thanks!

2 个解决方案

#1


3  

The answer is that Enterprise Library by default uses the exe's config file. If you're producing a dll, including COM, then for good reason you might not want to depend on the calling executable. One solution to this (there might be others) is to create the Enterprise Library objects yourself instead of using the default ones, and tell them where to get the configuration from. This isn't as scary as it seems and doesn't require recompiling entlib or anything like that.

答案是Enterprise Library默认使用exe的配置文件。如果你正在生成一个dll,包括COM,那么你可能不想依赖于调用可执行文件。对此(可能还有其他)的一个解决方案是自己创建企业库对象而不是使用默认对象,并告诉他们从哪里获取配置。这并不像看起来那么可怕,也不需要重新编译entlib或类似的东西。

Instead of simply using Logger.Write() I did the following: a) Create the log writer, using the dll's config file:

我没有简单地使用Logger.Write(),而是执行以下操作:a)使用dll的配置文件创建日志编写器:

        string dllConfigFilename = Assembly.GetExecutingAssembly().Location + ".config";
        FileConfigurationSource exceptionsSource = new FileConfigurationSource(dllConfigFilename);
        LogWriterFactory writerFactory = new LogWriterFactory(exceptionsSource);
        logWriter = writerFactory.Create();

b) Then use this log writer within your code:

b)然后在代码中使用此日志编写器:

        LogEntry log = new LogEntry();
        log.Message = message;
        log.Categories = new string[] { "General" };
        logWriter.Write(log);

Here's the full code for a sample object I created. The references were Microsoft.Practices.EnterpriseLibrary.Common, Microsoft.Practices.EnterpriseLibrary.Logging, Microsoft.Practices.ObjectBuilder, System, System.Data, System.Windows.Forms, System.Xml:

这是我创建的示例对象的完整代码。参考文献是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;
        }
    }

}

The project included a COMThing.dll.config file which i set 'Copy to Output Directory' to 'Copy always'. This is a trivial config that writes log information to the Application Event Log. The contents of the config file are:

该项目包括一个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>

In the project properties under Build check 'Register for COM interop'. Build the project, then create the following .vbs file:

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

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

If you double-click this vbs file it should show a message box with the text 'called from com by vbs' and write an entry to your Application Event Log. This demonstrates that while the executing process is C:\WINDOWS\System32\WScript.exe (or similar), it's getting the config from your dll's config file.

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

I based this on the information here under 'Using Several ConfigurationSources'.

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

Note that the Logger class includes lots of nice helper methods with different arguments. Since we're using the LogWriter class we don't get this magic. Personally I'll be creating another class within my library to perform the same job, based on Logger.

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

The referenced article shows the same principle applied to Database and Exception application blocks. Presumably the same model can be applied to most/all of them.

引用的文章显示了应用于Database和Exception应用程序块的相同原则。据推测,相同的模型可以应用于大多数/所有模型。

#2


0  

Check the related issue which i had faced . Maybe its of some help.

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

How to include COM components on a published .Net site?

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

#1


3  

The answer is that Enterprise Library by default uses the exe's config file. If you're producing a dll, including COM, then for good reason you might not want to depend on the calling executable. One solution to this (there might be others) is to create the Enterprise Library objects yourself instead of using the default ones, and tell them where to get the configuration from. This isn't as scary as it seems and doesn't require recompiling entlib or anything like that.

答案是Enterprise Library默认使用exe的配置文件。如果你正在生成一个dll,包括COM,那么你可能不想依赖于调用可执行文件。对此(可能还有其他)的一个解决方案是自己创建企业库对象而不是使用默认对象,并告诉他们从哪里获取配置。这并不像看起来那么可怕,也不需要重新编译entlib或类似的东西。

Instead of simply using Logger.Write() I did the following: a) Create the log writer, using the dll's config file:

我没有简单地使用Logger.Write(),而是执行以下操作:a)使用dll的配置文件创建日志编写器:

        string dllConfigFilename = Assembly.GetExecutingAssembly().Location + ".config";
        FileConfigurationSource exceptionsSource = new FileConfigurationSource(dllConfigFilename);
        LogWriterFactory writerFactory = new LogWriterFactory(exceptionsSource);
        logWriter = writerFactory.Create();

b) Then use this log writer within your code:

b)然后在代码中使用此日志编写器:

        LogEntry log = new LogEntry();
        log.Message = message;
        log.Categories = new string[] { "General" };
        logWriter.Write(log);

Here's the full code for a sample object I created. The references were Microsoft.Practices.EnterpriseLibrary.Common, Microsoft.Practices.EnterpriseLibrary.Logging, Microsoft.Practices.ObjectBuilder, System, System.Data, System.Windows.Forms, System.Xml:

这是我创建的示例对象的完整代码。参考文献是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;
        }
    }

}

The project included a COMThing.dll.config file which i set 'Copy to Output Directory' to 'Copy always'. This is a trivial config that writes log information to the Application Event Log. The contents of the config file are:

该项目包括一个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>

In the project properties under Build check 'Register for COM interop'. Build the project, then create the following .vbs file:

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

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

If you double-click this vbs file it should show a message box with the text 'called from com by vbs' and write an entry to your Application Event Log. This demonstrates that while the executing process is C:\WINDOWS\System32\WScript.exe (or similar), it's getting the config from your dll's config file.

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

I based this on the information here under 'Using Several ConfigurationSources'.

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

Note that the Logger class includes lots of nice helper methods with different arguments. Since we're using the LogWriter class we don't get this magic. Personally I'll be creating another class within my library to perform the same job, based on Logger.

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

The referenced article shows the same principle applied to Database and Exception application blocks. Presumably the same model can be applied to most/all of them.

引用的文章显示了应用于Database和Exception应用程序块的相同原则。据推测,相同的模型可以应用于大多数/所有模型。

#2


0  

Check the related issue which i had faced . Maybe its of some help.

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

How to include COM components on a published .Net site?

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