private void StopTrace2() { int count; IntPtr[] a = new IntPtr[64]; for (int i = 0; i < a.Length; i++) { int size; a[i] = BuildProperties(true, out size); } int hr = QueryAllTraces(a, a.Length, out count); if (hr == 0) { for (int i = 0; i < count; i++) { EVENT_TRACE_PROPERTIES propi = (EVENT_TRACE_PROPERTIES)Marshal.PtrToStructure(a[i], typeof(EVENT_TRACE_PROPERTIES)); if (propi.Wnode.Guid == ProviderGuid) { StopTrace(propi.Wnode.HistoricalContext, null, a[i]); } } } for (int i = 0; i < a.Length; i++) { Marshal.FreeCoTaskMem(a[i]); } }
public static IEnumerable <EVENT_TRACE_PROPERTIES> QueryAllTraces() { const int len = 64; var props = new List <SafeHGlobalHandle>(len); var loadProp = EVENT_TRACE_PROPERTIES.Create(); for (var i = 0; i < len; i++) { props.Add(SafeHGlobalHandle.CreateFromStructure(loadProp)); } try { var pprops = props.Select(p => (IntPtr)p).ToArray(); AdvApi32.QueryAllTraces(pprops, len, out var count).ThrowIfFailed(); for (var i = 0; i < count; i++) { yield return(props[i].ToStructure <EVENT_TRACE_PROPERTIES>()); } } finally { for (var i = 0; i < props.Count; i++) { props[i].Dispose(); } } }
private IntPtr BuildProperties(bool stopping, out int size) { IntPtr properties; var prop = new EVENT_TRACE_PROPERTIES(); if (stopping) { size = Marshal.SizeOf(typeof(EVENT_TRACE_PROPERTIES)) + (1024 + 1) * 2; properties = Marshal.AllocCoTaskMem(size); RtlZeroMemory(properties, (IntPtr)size); prop.Wnode.Guid = ProviderGuid; prop.Wnode.BufferSize = size; } else { size = Marshal.SizeOf(typeof(EVENT_TRACE_PROPERTIES)) + (SessionName.Length + 1) * 2; properties = Marshal.AllocCoTaskMem(size); RtlZeroMemory(properties, (IntPtr)size); prop.Wnode.Guid = ProviderGuid; prop.Wnode.Flags = WNODE_FLAG_TRACED_GUID; prop.Wnode.BufferSize = size; prop.LogFileMode = EVENT_TRACE_REAL_TIME_MODE; } prop.LoggerNameOffset = Marshal.SizeOf(typeof(EVENT_TRACE_PROPERTIES)); Marshal.StructureToPtr(prop, properties, false); return(properties); }
public void QueryTraceTest() { var sess = EventTraceSession.ActiveSessions.First(); var prop = EVENT_TRACE_PROPERTIES.Create(); Assert.That(QueryTrace(sess.TraceSessionHandle, null, ref prop), ResultIs.Successful); prop.WriteValues(); }
static void Main(string[] args) { Guid triggerProvider; uint triggerLevel = (uint)EventLevel.Error; uint triggerKeyword = 0; int res = 0; try { triggerProvider = Guid.Parse(args[0]); circularSessionName = args[1]; logFileName = args.Length > 2 ? args[2] : "Flush.etl"; } catch (Exception exception) { Console.WriteLine(exception.Message); Help(); return; } Console.WriteLine($"Start {triggerSessionName}"); Console.CancelKeyPress += (s, a) => StopTrace(); var triggerProperties = new EVENT_TRACE_PROPERTIES() { LogFileMode = LogFileMode.REAL_TIME_MODE | LogFileMode.USE_MS_FLUSH_TIMER, FlushTimer = 1, }; res = Native.StartTrace(out var triggerSessionHandle, triggerSessionName, triggerProperties); if (res != 0) { throw new Win32Exception(res); } res = Native.EnableTrace(1, triggerKeyword, triggerLevel, triggerProvider, triggerSessionHandle); Console.WriteLine($"Process {triggerSessionName}"); var triggerLog = new EVENT_TRACE_LOGFILEW { LoggerName = triggerSessionName, ProcessTraceMode = ProcessTraceMode.REAL_TIME | ProcessTraceMode.EVENT_RECORD, EventRecordCallback = EventRecordCallback, }; var triggerLogHandle = Native.OpenTraceW(ref triggerLog); res = Native.ProcessTrace(new[] { triggerLogHandle }, 1, 0, 0); if (res != 0) { Console.WriteLine(new Win32Exception(res).Message); } Native.CloseTrace(triggerLogHandle); StopTrace(); }
public void FlushTrace() { if (IsValid) { EVENT_TRACE_PROPERTIES properties = CommonEvenTraceProperties(); uint status = NativeMethods.ControlTrace(0, this.setting.Name, ref properties, (ulong)EventTraceControl.FLUSH); if (status != NativeMethods.ERROR_SUCCESS) { throw new Win32Exception((int)status); } } }
private void GetSessionHandle() { EVENT_TRACE_PROPERTIES properties = CommonEvenTraceProperties(); uint status = NativeMethods.ControlTrace(0, this.setting.Name, ref properties, (ulong)EventTraceControl.QUERY); if (status == NativeMethods.ERROR_SUCCESS) { _handle = properties.WNode.ContextVersion.HistoricalContext; } else { _handle = 0; } }
public void UpdateLogFileName(string newpath) { if (setting.RealTimeSession || setting.UseNewFileMode) { throw new NotSupportedException("Updating session log file name is not supported for real-time session or EVENT_TRACE_FILE_MODE_NEWFILE mode"); } EVENT_TRACE_PROPERTIES properties = CommonEvenTraceProperties(); // Set LogFileNameOffset member if you want to switch to another log file. properties.LogFileNameOffset = EventTracePropertiesMarshalSize.StructSize + EventTracePropertiesMarshalSize.StringSize1; properties.LogFileName = newpath; uint status = NativeMethods.ControlTrace(0, this.setting.Name, ref properties, (ulong)EventTraceControl.UPDATE); }
/// <summary> /// Create an ETW session /// </summary> public void StartTrace() { if (_handle == 0) { EVENT_TRACE_PROPERTIES properties = CommonEvenTraceProperties(); properties.WNode.Flags = WNodeFlags.TracedGuid; properties.WNode.ClientContext = 1; //QPC clock resolution properties.BufferSize = (uint)setting.BufferSize; properties.MinimumBuffers = (uint)setting.MinBuffers; properties.MaximumBuffers = (uint)setting.MaxBuffers; if (setting.RealTimeSession) { // real time mode properties.LogFileMode = EventTraceFileMode.RealTime; } else if (setting.UseNewFileMode) { // NewFile mode properties.LogFileMode = EventTraceFileMode.NewFile; properties.MaximumFileSize = (uint)this.setting.MaxFileSize; properties.FlushTimer = (uint)this.setting.FlushTimer; } else { // rolling file hourly. properties.LogFileMode = EventTraceFileMode.FileSequential; properties.MaximumFileSize = 0; properties.FlushTimer = (uint)this.setting.FlushTimer; } // From MSDN: // Uses paged memory. This setting is recommended so that events do not use up the nonpaged memory. // Kernel-mode providers cannot log events to sessions that specify this logging mode. if (setting.UsePagedMemory) { properties.LogFileMode |= EventTraceFileMode.UsePagedMemory; } uint processResult = NativeMethods.StartTrace(out _handle, setting.Name, ref properties); if (processResult != NativeMethods.ERROR_SUCCESS && processResult != NativeMethods.ERROR_ALREADY_EXISTS) { throw new Win32Exception((int)processResult); } } // if _handle != 0, the session has already been created }
public void EventAccessTest() { var etp = EVENT_TRACE_PROPERTIES.Create(Guid.NewGuid()); etp.LogFileMode = LogFileMode.EVENT_TRACE_FILE_MODE_SEQUENTIAL; etp.MaximumFileSize = 1; etp.LogFileName = logfilePath; etp.LoggerName = "MySession"; var sess = new EventTraceSession(etp); var sz = 1024U; using var sd = new SafePSECURITY_DESCRIPTOR((int)sz); Assert.That(EventAccessQuery(sess.ProviderGuid, sd, ref sz), ResultIs.Successful); Assert.That(EventAccessControl(sess.ProviderGuid, EVENTSECURITYOPERATION.EventSecurityAddDACL, SafePSID.Current, TRACELOG_RIGHTS.WMIGUID_QUERY, true), ResultIs.Successful); Assert.That(EventAccessRemove(sess.ProviderGuid), ResultIs.Successful); }
/// <summary> /// Stops and delete the session /// </summary> public void StopTrace() { if (_handle != 0) { EVENT_TRACE_PROPERTIES properties = CommonEvenTraceProperties(); uint processResult = NativeMethods.StopTrace(_handle, setting.Name, ref properties); if (processResult != NativeMethods.ERROR_SUCCESS && processResult != NativeMethods.ERROR_CANCELLED && processResult != NativeMethods.ERROR_WMI_INSTANCE_NOT_FOUND) // It is expected that the ETW session might not exist { throw new Win32Exception((int)processResult); } _handle = 0; } }
private EVENT_TRACE_PROPERTIES CommonEvenTraceProperties() { EVENT_TRACE_PROPERTIES properties = new EVENT_TRACE_PROPERTIES(); properties.WNode.BufferSize = EventTracePropertiesMarshalSize.StructSize + EventTracePropertiesMarshalSize.StringSize1 + EventTracePropertiesMarshalSize.StringSize2; properties.WNode.Flags = WNodeFlags.TracedGuid; properties.LoggerNameOffset = EventTracePropertiesMarshalSize.StructSize; if (this.setting.LogFilePath == null) { // real time session properties.LogFileNameOffset = 0; } else { // file mode // copy the log file path properties.LogFileNameOffset = EventTracePropertiesMarshalSize.StructSize + EventTracePropertiesMarshalSize.StringSize1; properties.LogFileName = setting.LogFilePath; } return(properties); }
private IntPtr BuildProperties(bool stopping, out int size) { IntPtr properties; EVENT_TRACE_PROPERTIES prop = new EVENT_TRACE_PROPERTIES(); if (stopping) { size = Marshal.SizeOf(typeof(EVENT_TRACE_PROPERTIES)) + (1024 + 1) * 2; properties = Marshal.AllocCoTaskMem(size); RtlZeroMemory(properties, (IntPtr)size); prop.Wnode.Guid = ProviderGuid; prop.Wnode.BufferSize = size; } else { size = Marshal.SizeOf(typeof(EVENT_TRACE_PROPERTIES)) + (SessionName.Length + 1) * 2; properties = Marshal.AllocCoTaskMem(size); RtlZeroMemory(properties, (IntPtr)size); prop.Wnode.Guid = ProviderGuid; prop.Wnode.Flags = WNODE_FLAG_TRACED_GUID; prop.Wnode.BufferSize = size; prop.LogFileMode = EVENT_TRACE_REAL_TIME_MODE; } prop.LoggerNameOffset = Marshal.SizeOf(typeof(EVENT_TRACE_PROPERTIES)); Marshal.StructureToPtr(prop, properties, false); return properties; }
internal extern static int StartKernelTrace( out UInt64 TraceHandle, EVENT_TRACE_PROPERTIES* Properties, STACK_TRACING_EVENT_ID* StackTracingEventIds, // Actually an array of code:STACK_TRACING_EVENT_ID int cStackTracingEventIds);
internal static extern int ControlTrace( ulong sessionHandle, string sessionName, EVENT_TRACE_PROPERTIES* properties, uint controlCode);
internal extern static int StartTraceW( [Out] out UInt64 sessionHandle, [In] string sessionName, EVENT_TRACE_PROPERTIES* properties);
static void StopTrace() { var stopProperties = new EVENT_TRACE_PROPERTIES(); Native.StopTrace(0, triggerSessionName, stopProperties); }
private void StartSession() { int status = 0; string path = LogFilePath; // Allocate memory for the session properties. The memory must // be large enough to include the log file name and session name, // which get appended to the end of the session properties structure. uint structSize = (uint)Marshal.SizeOf(typeof(EVENT_TRACE_PROPERTIES)); uint pathSize = (uint)(sizeof(char) * path.Length) + 1; uint sessionNameSize = (uint)(sizeof(char) * this.eventLogSessionName.Length) + 1; uint bufferSize = structSize + pathSize + sessionNameSize; EVENT_TRACE_PROPERTIES pSessionProperties = new EVENT_TRACE_PROPERTIES(); this.traceProperties = Marshal.AllocCoTaskMem((int)bufferSize); if (this.traceProperties == IntPtr.Zero) { throw new OutOfMemoryException(); } try { // Set the session properties. You only append the log file name // to the properties structure; the StartTrace function appends // the session name for you. const int WNODE_FLAG_TRACED_GUID = 0x00020000; const int EVENT_TRACE_REAL_TIME_MODE = 0x00000100; const int ERROR_ALREADY_EXISTS = 183; pSessionProperties.Wnode.BufferSize = bufferSize; pSessionProperties.Wnode.Flags = WNODE_FLAG_TRACED_GUID; pSessionProperties.Wnode.ClientContext = 1; //QPC clock resolution pSessionProperties.Wnode.Guid = sessionGuid; pSessionProperties.LogFileMode = EVENT_TRACE_REAL_TIME_MODE; // EVENT_TRACE_FILE_MODE_SEQUENTIAL; pSessionProperties.MaximumFileSize = 1; // 1 MB pSessionProperties.LoggerNameOffset = structSize; pSessionProperties.LogFileNameOffset = structSize + pathSize; // Copy the data to the buffer Marshal.StructureToPtr(pSessionProperties, this.traceProperties, false); CopyString(path, new IntPtr((long)this.traceProperties + structSize)); CopyString(this.eventLogSessionName, new IntPtr((long)this.traceProperties + structSize + pathSize)); this.sessionHandle = 0; // Create the trace session. status = NativeMethods.StartTrace(out sessionHandle, this.eventLogSessionName, this.traceProperties); if (status == ERROR_ALREADY_EXISTS) { // close unclosed previous trace. StopTrace(); status = NativeMethods.StartTrace(out sessionHandle, this.eventLogSessionName, this.traceProperties); } if (0 != status) { throw new System.ComponentModel.Win32Exception(status); } } finally { } }