Entlib и interop: это работает, и куда идет файл конфигурации? - PullRequest
1 голос
/ 11 декабря 2008

Я пытаюсь использовать EntLib 3.1 внутри кода .net для DLL, которая зарегистрирована для взаимодействия COM. Куда мне положить файл конфигурации?

В качестве альтернативы, есть ли способ указать в коде dll, откуда он должен получить конфигурацию entlib? Поскольку мой dll будет вызываться из COM, я не всегда знаю, какой exe будет вызывать его.

Я создал простое приложение, которое использует Entlib Logging, с двумя классами: 'CallingApp' и 'MyComThing'. Когда я вызываю метод MyComThing из CallingApp, он регистрируется с использованием конфигурации в файле конфигурации CallingApp. Когда я вызываю метод MyComThing из сценария vbs, т.е. через COM, я получаю сообщение об ошибке «Раздел конфигурации для ведения журнала не может быть найден в источнике конфигурации». Мой файл COMThing.dll.config находится в той же папке, что и зарегистрированный файл COMThing.dll, то есть в папке bin \ debug \.

спасибо!

Ответы [ 2 ]

3 голосов
/ 11 декабря 2008

Ответ заключается в том, что Enterprise Library по умолчанию использует файл конфигурации exe. Если вы создаете dll, включая COM, то по понятной причине вы можете не зависеть от вызывающего исполняемого файла. Одно из решений этого (может быть и других) состоит в том, чтобы создать объекты Enterprise Library самостоятельно, а не использовать объекты по умолчанию, и сообщить им, где получить конфигурацию. Это не так страшно, как кажется, и не требует перекомпиляции 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>

В свойствах проекта в разделе «Сборка» установите флажок «Зарегистрироваться для взаимодействия COM». Создайте проект, затем создайте следующий файл .vbs:

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

Если вы дважды щелкнете по этому VBS-файлу, в нем должно появиться окно сообщения с текстом «вызываемый из VBS» и запись в журнал событий вашего приложения. Это демонстрирует, что, хотя выполняющийся процесс - C: \ WINDOWS \ System32 \ WScript.exe (или аналогичный), он получает конфигурацию из файла конфигурации вашей dll.

Я основал это на информации здесь в разделе «Использование нескольких источников конфигурации».

Обратите внимание, что класс Logger включает множество хороших вспомогательных методов с различными аргументами. Поскольку мы используем класс LogWriter, мы не получаем этой магии. Лично я буду создавать другой класс в своей библиотеке для выполнения той же работы на основе Logger.

В указанной статье показан тот же принцип, который применяется к блокам базы данных и исключений. Предположительно одна и та же модель может быть применена к большинству / всем из них.

0 голосов
/ 11 декабря 2008

Проверьте связанную проблему, с которой я столкнулся. Может быть, это поможет.

Как включить компоненты COM в опубликованный сайт .Net?

...