/// <summary> /// Writes out trace data. data should be a series of structures, starting with a /// EVENT_TRACE_HEADER structure. /// </summary> /// <param name="data"></param> public void Trace(EVENT_TRACE_HEADER header, params object[] data) { IntPtr traceData; int size = Marshal.SizeOf(typeof(EVENT_TRACE_HEADER)); for (int i = 0; i < data.Length; i++) { string strData; byte[] asciiStrData; if ((strData = data[i] as string) != null) { size += strData.Length * 2 + 2; } else if ((asciiStrData = data[i] as byte[]) != null) { size += asciiStrData.Length + 1; } else { size += Marshal.SizeOf(data[i]); } } IntPtr tempData = traceData = Marshal.AllocHGlobal(size); try { if (traceData == IntPtr.Zero) { throw new OutOfMemoryException(); } tempData = new IntPtr(tempData.ToInt64() + Marshal.SizeOf(typeof(EVENT_TRACE_HEADER))); for (int i = 0; i < data.Length; i++) { string strData; byte[] asciiStrData; if ((strData = data[i] as string) != null) { for (int j = 0; j < strData.Length; j++) { Marshal.WriteInt16(tempData, j * 2, strData[j]); } Marshal.WriteInt16(tempData, strData.Length * 2, 0); tempData = new IntPtr(tempData.ToInt64() + strData.Length * 2 + 2); } else if ((asciiStrData = data[i] as byte[]) != null) { for (int j = 0; j < asciiStrData.Length; j++) { Marshal.WriteByte(tempData, j, asciiStrData[j]); } Marshal.WriteByte(tempData, asciiStrData.Length, 0); tempData = new IntPtr(tempData.ToInt64() + asciiStrData.Length + 1); } else { Marshal.StructureToPtr(data[i], tempData, false); tempData = new IntPtr(tempData.ToInt64() + Marshal.SizeOf(data[i])); } } header.Size = (ushort)size; Marshal.StructureToPtr(header, traceData, false); var res = EtlNativeMethods.TraceEvent(_handle, traceData); if (res != 0) { throw new Win32Exception((int)res); } } finally { Marshal.FreeHGlobal(traceData); } }