C# ETW / Microsoft-Windows-Winsock-AFD 事件未完成

问题描述

跑步时:
logman start -ets HackingSeriesSession -o hss.etl -p Microsoft-Windows-Winsock-AFD

等待 10 秒,然后:
logman stop -ets HackingSeriesSession tracerpt.exe hss.etl -o evidence.txt

你得到:

<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
    <System>
        <Provider Name="Microsoft-Windows-Winsock-AFD" Guid="{e53c6823-7bb8-44bb-90dc-3f86090d48a6}" />
        <EventID>1018</EventID>
        <Version>0</Version>
        <Level>4</Level>
        <Task>1018</Task>
        <Opcode>11</Opcode>
        <Keywords>0x8000000000000006</Keywords>
        <TimeCreated SystemTime="2021-02-24T20:01:49.648516100+00:59" />
        <Correlation ActivityID="{3ecdd6a0-c708-ffff-0000-000000000000}" />
        <Execution ProcessID="3780" ThreadID="6552" ProcessorID="6" KernelTime="210" UserTime="210" />
        <Channel>Microsoft-Windows-Winsock-AFD/Operational</Channel>
        <Computer />
    </System>
    <EventData>
        <Data Name="EnterExit">       0</Data>
        <Data Name="Location">    5023</Data>
        <Data Name="Process">0xFFFFC7083D1440C0</Data>
        <Data Name="Endpoint">0xFFFFC7083ECDD6A0</Data>
        <Data Name="Buffer">0x0</Data>
        <Data Name="BufferLength">       0</Data>
        <Data Name="Status">0x0</Data>
        <Data Name="AddressLen">      16</Data>
        <Data Name="Address">127.0.0.1:1120</Data>
    </EventData>
    <RenderingInfo Culture="en-DE">
        <Level>information </Level>
        <Opcode>Bound </Opcode>
        <Keywords>
            <Keyword>Stream socket </Keyword>
            <Keyword>Winsock initiated event </Keyword>
        </Keywords>
        <Task>AfdConnectWithAddress</Task>
        <Message>connect: 0: Process 0xFFFFC7083D1440C0,Endpoint 0xFFFFC7083ECDD6A0,Address 127.0.0.1:1120,Seq 5023,Status STATUS_SUCCESS </Message>
        <Channel>Microsoft-Windows-Winsock Network Event/Operational </Channel>
        <Provider>Microsoft-Windows-Winsock Network Event </Provider>
    </RenderingInfo>
</Event>
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">

这很好,但现在我想在 C# 中使用相同的 AFD 东西和 MS EventTraceProvider 代码。在网上找到了一些例子,只切换了这一行:

var restarted = session.EnableProvider("Microsoft-Demos-SimpleMonitor");
            

这样:

var restarted = session.EnableProvider("Microsoft-Windows-Winsock-AFD");

但控制台输出中的结果只包含几个值:

GOT Event Delay=2,0sec: <Event MSec=   "939,9642" PID="13932" PName=        "" TID="16040" ActivityID="36e4cdc0c708ffff0000000000000000" EventName="AfdSend/Connected" ProviderName="Microsoft-Windows-Winsock-AFD" FormattedMessage="send: 0: Process 0xffffc708408350c0,Endpoint 0xffffc70849f8d010,Buffer Count 1,Buffer 0xffffc7084ab8aba0,Length 63,Seq 3.000,Status 0 " EnterExit="0" Location="3.000" Process="0xffffc708408350c0" Endpoint="0xffffc70849f8d010" BufferCount="1" Buffer="0xffffc7084ab8aba0" BufferLength="63" Status="0"/>

你如何获得像tracert.exe这样生成的其余信息?

using Microsoft.Diagnostics.Tracing;
using Microsoft.Diagnostics.Tracing.Session;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using TraceEventSamples.Producer;

/* README FirsT */
// This program is a simple demo that demonstrates both the EventSource to generate ETL events as 
// well as using the ETWTraceEventSource class to read the resulting ETW events in real time.   
//
// The basic flow of the program is
//     * Create a 'real time' TraceEventSession.  This lets you control what events you wish to collect
//     * Connect a ETWTraceEventSource for the session using the 'Source' property.   A TraceEventSource 
//           represents the stream of events coming from the session.  
//     * Connect a TraceEventParser to the source.    Parsers kNow how to interpret events from particular 
//          ETW providers.  In this case we care about EVentSource events and the DynamicTraceEventParser
//          is the parser that cares about it.  
//     * Attach callbacks to the Parser for the events you are interested in.  We use the 'All' C# event 
//          for this.  
//     * Enable the ETW providers of interest (in this case Microsoft-Demos-SimpleMonitor) 
//     * Kick off EventGenerator to generate some Microsoft-Demos-SimpleMonitor events (normally in another process).  
//     * Call the ETWTraceEventSource.Process() method,which waits for events and sends them to the callbacks. 
//     * At this point callbacks get called when the events come in.  
//     
// After 'Process()' is called,it will return if
//     * ETWTraceEventSource.StopProcessing() is called.
//     * The TraceEventSession.dispose() is called.  
namespace TraceEventSamples
{
    /// <summary>
    /// The main program is the 'listener' that listens and processes the events that come from ANY 
    /// process that is generating Microsoft-Demos-SimpleMonitor events.  
    /// </summary>
    internal class SimpleEventSourceMonitor
    {
        private static TextWriter Out = Console.Out;

        /// <summary>
        /// This is a demo of using TraceEvent to activate a 'real time' provider that is listening to 
        /// the MyEventSource above.   normally this event source would be in a different process,but 
        /// it also works if this process generate the events and I do that here for simplicity.  
        /// </summary>
        public static int Main()
        {
            Out.WriteLine("******************** SimpleEventSourceMonitor DEMO ********************");
            Out.WriteLine("This program generates processes and displays EventSource events");
            Out.WriteLine("using the ETW REAL TIME pipeline. (thus no files are created)");
            Out.WriteLine();

            // Today you have to be Admin to turn on ETW events (anyone can write ETW events).   
            if (!(TraceEventSession.IsElevated() ?? false))
            {
                Out.WriteLine("To turn on ETW events you need to be Administrator,please run from an Admin process.");
                Debugger.Break();
                return -1;
            }

            // To listen to ETW events you need a session,which allows you to control which events will be produced
            // Note that it is the session and not the source that buffers events,and by default sessions will buffer
            // 64MB of events before dropping events.  Thus even if you don't immediately connect up the source and
            // read the events you should not lose them. 
            //
            // As mentioned below,sessions can outlive the process that created them.  Thus you may need a way of 
            // naming the session so that you can 'reconnect' to it from another process.   This is what the name
            // is for.  It can be anything,but it should be descriptive and unique.   If you expect multiple versions
            // of your program to run simultaneously,you need to generate unique names (e.g. add a process ID suffix) 
            // however this is dangerous because you can leave data collection on if the program ends unexpectedly.  
            var sessionName = "SimpleMontitorSession";
            Out.WriteLine("Creating a '{0}' session",sessionName);
            Out.WriteLine("Use 'logman query -ets' to see active sessions.");
            Out.WriteLine("Use 'logman stop {0} -ets' to manually stop orphans.",sessionName);
            using (var session = new TraceEventSession(sessionName))
            {
                /* BY DEFAULT ETW SESSIONS SURVIVE THE DEATH OF THE PROESS THAT CREATES THEM! */
                // Unlike most other resources on the system,ETW session live beyond the lifetime of the 
                // process that created them.   This is very useful in some scenarios,but also creates the 
                // very real possibility of leaving 'orphan' sessions running.  
                //
                // To help avoid this by default TraceEventSession sets 'StopOndispose' so that it will stop
                // the ETW session if the TraceEventSession dies.   Thus executions that 'clean up' the TraceEventSession
                // will clean up the ETW session.   This covers many cases (including throwing exceptions)
                //  
                // However if the process is killed manually (including control C) this cleanup will not happen.  
                // Thus best practices include
                //
                //     * Add a Control C handler that calls session.dispose() so it gets cleaned up in this common case
                //     * use the same session name (say your program name) run-to-run so you don't create many orphans. 
                //
                // By default TraceEventSessions are in 'create' mode where it assumes you want to create a new session.
                // In this mode if a session already exists,it is stopped and the new one is created.   
                // 
                // Here we install the Control C handler.   It is OK if dispose is called more than once.  
                Console.CancelKeyPress += delegate (object sender,ConsoleCancelEventArgs e) { session.dispose(); };

                // To demonstrate non-trivial event manipulation,we calculate the time delta between 'MyFirstEvent and 'MySecondEvent'
                // firstEventTimeMSec remembers all the 'MyFirstEvent' arrival times (indexed by their ID)  
                var firstEventTimeMSec = new Dictionary<int,double>();

                /*****************************************************************************************************/
                // Hook up events.   To do this we first  need a 'Parser. which kNows how to part the events of a particular Event Provider.
                // In this case we get a DynamicTraceEventSource,which kNows how to parse any EventSource provider.    This parser
                // is so common,that TraceEventSource has a shortcut property called 'Dynamic' that fetches this parser.  

                // For debugging,and demo purposes,hook up a callback for every event that 'Dynamic' kNows about (this is not EVERY
                // event only those kNown about by DynamiceTraceEventParser).   However the 'UnhandledEvents' handler below will catch
                // the other ones.
                session.source.Dynamic.All += delegate (TraceEvent data)
                {
                    // ETW buffers events and only delivers them after buffering up for some amount of time.  Thus 
                    // there is a small delay of about 2-4 seconds between the timestamp on the event (which is very 
                    // accurate),and the time we actually get the event.  We measure that delay here.     
                    var delay = (DateTime.Now - data.TimeStamp).TotalSeconds;
                    Out.WriteLine("GOT Event Delay={0:f1}sec: {1} ",delay,data.ToString());
                };

                // Add logic on what to do when we get "MyFirstEvent"
                session.source.Dynamic.AddCallbackForProviderEvent("Microsoft-Demos-SimpleMonitor","MyFirstEvent",delegate (TraceEvent data)
                {
                    // On First Events,simply remember the ID and time of the event
                    firstEventTimeMSec[(int)data.PayloadByName("MyId")] = data.TimeStampRelativeMSec;
                });

                // Add logic on what to do when we get "MySecondEvent"
                session.source.Dynamic.AddCallbackForProviderEvent("Microsoft-Demos-SimpleMonitor","MySecondEvent",delegate (TraceEvent data)
                {
                    // On Second Events,if the ID matches,compute the delta and display it. 
                    var myID = (int)data.PayloadByName("MyId");
                    double firstEventTime;
                    if (firstEventTimeMSec.TryGetValue(myID,out firstEventTime))
                    {
                        firstEventTimeMSec.Remove(myID);            // We are done with the ID after matching it,so remove it from the table. 
                        Out.WriteLine("   >>> Time Delta from first Event = {0:f3} MSec",data.TimeStampRelativeMSec - firstEventTime);
                    }
                    else
                    {
                        Out.WriteLine("   >>> WARNING,Found a 'SecondEvent' without a corresponding 'FirstEvent'");
                    }
                });

                // Add logic on what to do when we get "Stop"
                session.source.Dynamic.AddCallbackForProviderEvent("Microsoft-Demos-SimpleMonitor","MyStopEvent",delegate (TraceEvent data)
                {
                    Out.WriteLine("    >>> Got a stop message");
                    // Stop processing after we we see the 'Stop' event,this will 'Process() to return.   It is OK to call dispose twice 
                    session.source.dispose();
                });

#if DEBUG
                // The callback above will only be called for events the parser recognizes (in the case of DynamicTraceEventParser,EventSources)
                // It is sometimes useful to see the other events that are not otherwise being handled.  The source kNows about these and you 
                // can ask the source to send them to you like this.  
                session.source.UnhandledEvents += delegate (TraceEvent data)
                {
                    if ((int)data.ID != 0xFFFE)         // The EventSource manifest events show up as unhanded,filter them out.
                        Out.WriteLine("GOT UNHANDLED EVENT: " + data.Dump());
                };
#endif
                // At this point we have created a TraceEventSession,hooked it up to a TraceEventSource,and hooked the
                // TraceEventSource to a TraceEventParser (you can do several of these),and then hooked up callbacks
                // up to the TraceEventParser (again you can have several).  However we have NOT actually told any
                // provider (EventSources) to actually send any events to our TraceEventSession.  
                // We do that Now.  

                // Enable my provider,you can call many of these on the same session to get events from other providers.  
                // Because this EventSource did not define any keywords,I can only turn on all events or none.  
                //var restarted = session.EnableProvider("Microsoft-Demos-SimpleMonitor");
                var restarted = session.EnableProvider("Microsoft-Windows-Winsock-AFD");
                if (restarted)      // Generally you don't bother with this warning,but for the demo we do. 
                {
                    Out.WriteLine("The session {0} was already active,it has been restarted.",sessionName);
                }

                // Start another thread that Causes MyEventSource to create some events
                // normally this code as well as the EventSource itself would be in a different process.  
                //EventGenerator.CreateEvents();

                Out.WriteLine("**** Start listening for events from the Microsoft-Demos-SimpleMonitor provider.");
                // go into a loop processing events can calling the callbacks.  Because this is live data (not from a file)
                // processing never completes by itself,but only because someone called 'source.dispose()'.  
                session.source.Process();
                Out.WriteLine();
                Out.WriteLine("Stopping the collection of events.");
            }
            return 0;
        }
    }
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)