2、TraceFile类代表一个trace文件,它既可以是capture trace的输出文件,也可以是replay trace的输入文件,下面的代码将traceFile对象设为traceServer所代表的trace的输出文件,最后一行为traceFile增加了一个WriteNotify事件的event handler,通过它我们将对输出做一些过滤。
TraceFile traceFile = new TraceFile();
traceFile.InitializeAsWriter(traceServer, @"d:\tracefile.trc");
traceFile.WriteNotify += new WriteNotifyEventHandler(WriteHandler);
traceFile.InitializeAsWriter(traceServer, @"d:\tracefile.trc");
traceFile.WriteNotify += new WriteNotifyEventHandler(WriteHandler);
3、这两个对象建立完毕,此时trace已经开始了,但tracefile.trc却始终是0字节,为什么呢?因为你还需要调用TraceFile类的Write函数来输出,但Write函数有两个问题,一是调用一次只输出一个trace event,你需要不停地调用它;二是Write函数是同步的,如果没有可以输出的内容的话它会阻塞,所以你需要另起一个线程来调用Write函数。
下面的代码启动WriteTraceProc线程并在60秒后结束capture trace。请注意traceServer.Close()必须在thread.Join()之前调用,否则WriteTraceProc线程可能会一直阻塞在Write函数调用上。
Thread thread = new Thread(WriteTraceProc);
thread.Start(traceFile); //pass traceFile as parameter
Thread.Sleep(60000);
lock (flagLock)
{
exitFlag = true;
}
traceServer.Close();
thread.Join();
traceFile.Close();
thread.Start(traceFile); //pass traceFile as parameter
Thread.Sleep(60000);
lock (flagLock)
{
exitFlag = true;
}
traceServer.Close();
thread.Join();
traceFile.Close();
4、接着是flagLock,exitFlag的定义及WriteTraceProc的代码,WriteTraceProc将持续调用Write直到exitFlag被主线程置为true。
private static object flagLock = new object();
private static bool exitFlag = false;
private static void WriteTraceProc(object obj)
{
TraceFile traceFile = (TraceFile)obj;
while (true)
{
lock (flagLock)
{
if (exitFlag)
break;
}
traceFile.Write();
}
}
private static bool exitFlag = false;
private static void WriteTraceProc(object obj)
{
TraceFile traceFile = (TraceFile)obj;
while (true)
{
lock (flagLock)
{
if (exitFlag)
break;
}
traceFile.Write();
}
}
5、最后是WriteHandler的代码,我们将使用EventClass列来过滤所有Audit Login及Audit Logout事件,你可以根据需要设置你的过滤条件。由于Books Online没有提供详细的文档,你也许需要使用IDataRecordChanger接口的GetName()来枚举所有你能使用的列。
private static void WriteHandler(object sender, TraceEventArgs args)
{
IDataRecordChanger recordChanger = args.CurrentRecord;
string eventClass = (string)recordChanger["EventClass"];
if (eventClass.StartsWith("Audit"))
args.SkipRecord = true;
}
{
IDataRecordChanger recordChanger = args.CurrentRecord;
string eventClass = (string)recordChanger["EventClass"];
if (eventClass.StartsWith("Audit"))
args.SkipRecord = true;
}