0

我想要完成的是仅使用配置文件在引用的 .dll 中为 TraceSource 设置 TraceListener。

具体来说,我有一个解决方案机器人,它的 app.config 如下所示:

<system.diagnostics>
<sources>
  <source name="RobotModel" switchValue="All">
    <listeners>
      <add name="RobotModelConsole" type="Ukadc.Diagnostics.Listeners.ConsoleTraceListener, Ukadc.Diagnostics" initializeData="{DateTime}::{EventType}::{Message}"/>
    </listeners>
  </source>
</sources/

和一个 ExtendedSource(来自 Ukadc.Diagnostics.dll)初始化如下:

public static ExtendedSource robotSourceEx = new ExtendedSource( "RobotModel", SourceLevels.All );

然后我导出 .dll 并将其导入 UI 组件并具有类似的 app.config:

 <system.diagnostics>
<sources>

  <source name="Temp" switchValue="All">
    <listeners>
      <!--<add name="console1" type="System.Diagnostics.ConsoleTraceListener" /> -->
      <add name="console" type="Ukadc.Diagnostics.Listeners.ConsoleTraceListener, Ukadc.Diagnostics" initializeData="{DateTime}::{EventType}::{Message}" />
    </listeners>
  </source>

  <source name="RobotModel" switchValue="All">
    <listeners>
      <add name="console1" type="Ukadc.Diagnostics.Listeners.ConsoleTraceListener, Ukadc.Diagnostics" initializeData="{DateTime}::{EventType}::{Message}" />
    </listeners>
  </source>

</sources>

当我运行 UI 组件时,我得到一个空控制台(Console.WriteLine 并且缺少跟踪信息),但是如果我注释掉 RobotModel 的 TraceListener,那么控制台会显示示例跟踪消息(以及 Console.WriteLine信息)。

  1. 我是否需要为 RobotModel TraceListener 指定 .dll 或命名空间
  2. 我知道我可以动态地执行此操作,因为我有一个获取跟踪消息的 winform 组件 TraceListener,但想从 app.config 配置它,假设这是可能的

注意:gui 是 Winforms/Windows 应用程序,而 Robot 类是控制台应用程序。我认为这不会有很大的不同,但也许值得注意。我确实在 Windows 应用程序上手动分配了一个控制台,以便在将其路由到文件之前确保跟踪工作正常。

4

2 回答 2

0

要将 TraceListener 设置为在程序集中定义的 TraceSource 以及仅使用配置文件的应用程序,我们可以使用 sharedListeners,如下所示:

申请代码:

using System;
using System.Diagnostics;
using TestLibrary;

namespace TraceSourceTest
{
    class Program
    {
        static TraceSource source = new TraceSource("TraceSourceTest");
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            source.TraceEvent(TraceEventType.Information, 101, "Hello World");
            Class1 test = new Class1();
            Console.WriteLine(test.add(5, 10));
            Console.ReadKey();
        }
    }
}

测试库代码:

using System.Diagnostics;
namespace TestLibrary
{
    public class Class1
    {
        static TraceSource source = new TraceSource("TestLibrary");
        public int add(int a, int b)
        {
            source.TraceEvent(TraceEventType.Information, 101, "Add " + a + " and " + b);
            source.TraceEvent(TraceEventType.Information, 102, "Result " + (a + b));
            return a + b;
        }
    }
}

应用程序配置:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
    </startup>
    <system.diagnostics>    
        <trace autoflush="true" indentsize="4" />
        <sources>
            <source name ="TestLibrary" switchValue="All">
                <listeners>    
                    <add name="testListener" />    
                </listeners>
            </source>
            <source name ="TraceSourceTest" switchValue="All">
                <listeners>    
                    <add name="testListener" />
                </listeners>
            </source>
        </sources>
        <sharedListeners>
            <add name="testListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="TraceSourceTest.log">
                <filter initializeData="All" type="System.Diagnostics.EventTypeFilter"/>
            </add>
        </sharedListeners>
    </system.diagnostics>
</configuration>

这将在应用程序运行的目录中创建一个 TraceSourceTest.log 文件,其中包含以下日志:

TraceSourceTest Information: 101 : Hello World
TestLibrary Information: 101 : Add 5 and 10
TestLibrary Information: 102 : Result 15

并且控制台将在输出下方打印:

Hello World!
15
于 2019-09-18T09:30:21.953 回答
0

回答我自己的问题:

  1. 不,在程序集中引用 TraceSource 时不需要指定 .dll 或命名空间,您只需要知道源的名称
  2. 是的,可以通过应用程序配置严格执行,如下所示

就导致我的问题的原因而言,它似乎与我在 WinForms 中分配控制台有关。更改我调用 AllocConsole 的位置后,cmd 窗口显示两个源的跟踪信息。

对于后代,这里是我用来测试这个的代码:

public class Person {
    public int Age { get; set; }
    public string Name { get; set; }
    public static TraceSource source = new TraceSource( "[Source]" );
    public static ExtendedSource exSource = new ExtendedSource( "[SourceEx]" );
    public Person ( int age, string name ) {
        source.TraceInformation( "Creating a person named: {0}", name );
        exSource.TraceInformation( "{0} is alive!", name );
        Age = age;
        Name = name;
    }

    public int DateOfBirth () {
        return 2018 - Age;
    }
}

然后将其导出为程序集,并将其导入到 winform:

namespace TestForm {
public partial class Form1 : Form {
    public static TraceSource source = new TraceSource( "[FormSource]" );
    public static ExtendedSource exSource = new ExtendedSource( "[FormSourceEx]", SourceLevels.All);
    public static int age;
    private int count = 0;

    [DllImport( "kernel32.dll", SetLastError = true )]
    [return: MarshalAs( UnmanagedType.Bool )]
    static extern bool AllocConsole ();

    public Form1 () {
        InitializeComponent();
    }

    private void button1_Click ( object sender, EventArgs e ) {
        source.TraceInformation( "Button Clicked" );
        exSource.TraceInformation( "Click count: {0}" ,count++ );
        Person p = new Person( age++, "Jordo" );
    }

    private void Form1_Load ( object sender, EventArgs e ) {
        AllocConsole();
    }
}
}

以及我使用的应用程序配置:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.diagnostics>
<sources>
  <source name="[Source]" switchValue="All">
    <listeners>
      <add name="console" type="Ukadc.Diagnostics.Listeners.ConsoleTraceListener, Ukadc.Diagnostics" initializeData="{Source}::{Hour}:{Minute}:{Second}:{Millisecond}::{EventType}::{Message}" />
    </listeners>
  </source>
  <source name="[SourceEx]" switchValue="All">
    <listeners>
      <add name="console" type="Ukadc.Diagnostics.Listeners.ConsoleTraceListener, Ukadc.Diagnostics" initializeData="{Source}::{Hour}:{Minute}:{Second}:{Millisecond}::{EventType}::{Message}" />
    </listeners>
  </source>
  <source name="[FormSource]" switchValue="All">
    <listeners>
      <add name="console1" type="Ukadc.Diagnostics.Listeners.ConsoleTraceListener, Ukadc.Diagnostics" initializeData="{Source}::{Hour}:{Minute}:{Second}:{Millisecond}::{EventType}::{Message}" />
    </listeners>
  </source>
  <source name="[FormSourceEx]" switchValue="All">
    <listeners>
      <add name="console2" type="Ukadc.Diagnostics.Listeners.ConsoleTraceListener, Ukadc.Diagnostics" initializeData="{Source}::{Hour}:{Minute}:{Second}:{Millisecond}::{EventType}::{Message}" />
    </listeners>
  </source>
</sources>
</system.diagnostics>
<startup> 
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
于 2018-07-20T19:03:53.313 回答