internal PropertyBag GetProperties(EventRecord eventRecord) { // We only support top level properties and simple types PropertyBag properties = new PropertyBag(_traceEventInfo.TopLevelPropertyCount); if (this._hasProperties) { int offset = 0; for (int i = 0; i < _traceEventInfo.TopLevelPropertyCount; i++) { EventPropertyInfo info = _eventPropertyInfoArray[i]; // Read the current property name string propertyName = Marshal.PtrToStringUni(new IntPtr(_address.ToInt64() + info.NameOffset)); object value; string mapName; int length; IntPtr dataPtr = new IntPtr(eventRecord.UserData.ToInt64() + offset); value = ReadPropertyValue(info, dataPtr, out mapName, out length); // If we have a map name, return both map name and map value as a pair. if (!string.IsNullOrEmpty(mapName)) { value = new KeyValuePair<string, object>(mapName, value); } offset += length; properties.Add(propertyName, value); } if (offset < eventRecord.UserDataLength) { // // There is some extra information not mapped. // IntPtr dataPtr = new IntPtr(eventRecord.UserData.ToInt64() + offset); int length = eventRecord.UserDataLength - offset; byte[] array = new byte[length]; for (int index = 0; index < length; index++) { array[index] = Marshal.ReadByte(dataPtr, index); } properties.Add("__ExtraPayload", array); } } else { // NOTE: It is just a guess that this is an Unicode string string str = Marshal.PtrToStringUni(eventRecord.UserData); properties.Add("EventData", str); } return properties; }
internal TraceEventInfoWrapper(EventRecord eventRecord) { Initialize(eventRecord); }
private void Initialize(EventRecord eventRecord) { int size = 0; const uint BufferTooSmall = 122; const uint ErrorlementNotFound = 1168; int error = NativeMethods.TdhGetEventInformation(ref eventRecord, 0, IntPtr.Zero, IntPtr.Zero, ref size); if (error == ErrorlementNotFound) { // Nothing else to do here. this._hasProperties = false; return; } this._hasProperties = true; if (error != BufferTooSmall) { throw new Win32Exception(error); } // Get the event information (schema) this._address = Marshal.AllocHGlobal(size); error = NativeMethods.TdhGetEventInformation(ref eventRecord, 0, IntPtr.Zero, _address, ref size); if (error != 0) { throw new System.ComponentModel.Win32Exception(error); } // Marshal the first part of the trace event information. _traceEventInfo = (TraceEventInfo)Marshal.PtrToStructure(this._address, typeof(TraceEventInfo)); // Marshal the second part of the trace event information, the array of property info. int actualSize = Marshal.SizeOf(this._traceEventInfo); if (size != actualSize) { int structSize = Marshal.SizeOf(typeof(EventPropertyInfo)); int itemsLeft = (size - actualSize) / structSize; this._eventPropertyInfoArray = new EventPropertyInfo[itemsLeft]; long baseAddress = _address.ToInt64() + actualSize; for (int i = 0; i < itemsLeft; i++) { IntPtr structPtr = new IntPtr(baseAddress + (i * structSize)); EventPropertyInfo info = (EventPropertyInfo)Marshal.PtrToStructure(structPtr, typeof(EventPropertyInfo)); this._eventPropertyInfoArray[i] = info; } } // Get the opcode name if (_traceEventInfo.OpcodeNameOffset > 0) { this.EventName = Marshal.PtrToStringUni(new IntPtr(_address.ToInt64() + _traceEventInfo.OpcodeNameOffset)); } }
private EventArrivedEventArgs CreateEventArgsFromEventRecord(EventRecord eventRecord) { byte eventOpcode = eventRecord.EventHeader.EventDescriptor.Opcode; TraceEventInfoWrapper traceEventInfo; bool shouldDispose = false; // Find the event information (schema). int index = this.traceEventInfoCache.IndexOfKey(eventOpcode); if (index >= 0) { traceEventInfo = this.traceEventInfoCache.Values[index]; } else { traceEventInfo = new TraceEventInfoWrapper(eventRecord); try { this.traceEventInfoCache.Add(eventOpcode, traceEventInfo); } catch (ArgumentException) { // Some other thread added this entry. shouldDispose = true; } } // Get the properties using the current event information (schema). PropertyBag properties = traceEventInfo.GetProperties(eventRecord); // Dispose the event information because it doesn't live in the cache if (shouldDispose) { traceEventInfo.Dispose(); } EventArrivedEventArgs args = new EventArrivedEventArgs(eventOpcode, properties); return args; }