我试图完成的是仅使用配置文件为引用的.dll中的TraceSource设置TraceListener。
具体来说,我有一个解决方案Robot,它有一个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.Diagnostic.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消息(。
- 我是否需要为RobotModel TraceListener指定.dll或命名空间
- 我知道我可以动态地做到这一点,因为我有一个获取跟踪消息的winform组件TraceListener,但我想从app.config中配置它,假设这是可能的
注意:gui是Winforms/Windows应用程序,而Robot类是控制台应用程序。我不认为这会有什么大的不同,但也许值得注意。我确实在Windows应用程序上手动分配了一个控制台,以便在将跟踪路由到文件之前确保跟踪工作正常。
回答我自己的问题:
- 不,引用程序集中的TraceSource时不需要指定.dll或命名空间,只需要知道源的名称
- 是的,可以严格通过应用程序配置来完成,如下所示
就导致我的问题的原因而言,这似乎与我在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>
要将TraceListener设置为在程序集和应用程序中定义的TraceSource,只需使用配置文件,我们可以使用sharedListener,如下所示:
应用程序代码:
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;
}
}
}
附录.config:
<?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