/// <summary>
        /// Starts a new trace log file with the given session name writing it to the specified file.
        /// 
        /// If a session name is not provided a unique name will be generated
        /// </summary>
        /// <param name="sessionName"></param>
        /// <param name="filename"></param>
        /// <returns></returns>
        public static TraceLog Start(string filename, string sessionName = null) {
            if (sessionName == null) {
                sessionName = Guid.NewGuid().ToString();
            }
            var bufferSize = Marshal.SizeOf(typeof(EVENT_TRACE_PROPERTIES)) +
                (sessionName.Length + 1) * 2 +
                (filename.Length + 1) * 2;

            var mem = Marshal.AllocHGlobal(bufferSize);
            for (int i = 0; i < bufferSize; i++) {
                Marshal.WriteByte(mem, i, 0);
            }

            if (mem == IntPtr.Zero) {
                throw new OutOfMemoryException();
            }

            EVENT_TRACE_PROPERTIES eventProps = new EVENT_TRACE_PROPERTIES();
            eventProps.Wnode.BufferSize = (uint)bufferSize;
            eventProps.BufferSize = 512;
            eventProps.Wnode.Guid = Guid.NewGuid();
            eventProps.LogFileMode = EVENT_TRACE_PRIVATE_IN_PROC | EVENT_TRACE_PRIVATE_LOGGER_MODE | EVENT_TRACE_FILE_MODE_SEQUENTIAL;
            eventProps.MaximumFileSize = 0;
            eventProps.Wnode.Flags = EtlNativeMethods.WNODE_FLAG_TRACED_GUID;
            eventProps.Wnode.TimeStamp = 0;
            eventProps.Wnode.ClientContext = 0;
            eventProps.LoggerNameOffset = (uint)Marshal.SizeOf(typeof(EVENT_TRACE_PROPERTIES));
            eventProps.LogFileNameOffset = (uint)(Marshal.SizeOf(typeof(EVENT_TRACE_PROPERTIES)) + (sessionName.Length + 1) * 2);

            Marshal.StructureToPtr(eventProps, mem, false);

            int offset = (int)eventProps.LogFileNameOffset;
            for (int i = 0; i < filename.Length; i++, offset += 2) {
                Marshal.WriteInt16(mem, offset, filename[i]);
            }
            Marshal.WriteInt16(mem, offset, 0);

            bool success = false;
            try {
                ulong handle;
                var error = EtlNativeMethods.StartTraceW(
                    out handle,
                    sessionName,
                    mem
                );

                if (error != 0) {
                    throw new Win32Exception((int)error);
                }

                var res = new TraceLog(handle, sessionName, mem);
                success = true;
                return res;
            } finally {
                if (!success) {
                    Marshal.FreeHGlobal(mem);
                }
            }
        }
Example #2
0
        /// <summary>
        /// Starts a new trace log file with the given session name writing it to the specified file.
        ///
        /// If a session name is not provided a unique name will be generated
        /// </summary>
        /// <param name="sessionName"></param>
        /// <param name="filename"></param>
        /// <returns></returns>
        public static TraceLog Start(string filename, string sessionName = null)
        {
            if (sessionName == null)
            {
                sessionName = Guid.NewGuid().ToString();
            }
            var bufferSize = Marshal.SizeOf(typeof(EVENT_TRACE_PROPERTIES)) +
                             (sessionName.Length + 1) * 2 +
                             (filename.Length + 1) * 2;

            var mem = Marshal.AllocHGlobal(bufferSize);

            for (int i = 0; i < bufferSize; i++)
            {
                Marshal.WriteByte(mem, i, 0);
            }

            if (mem == IntPtr.Zero)
            {
                throw new OutOfMemoryException();
            }

            EVENT_TRACE_PROPERTIES eventProps = new EVENT_TRACE_PROPERTIES();

            eventProps.Wnode.BufferSize    = (uint)bufferSize;
            eventProps.BufferSize          = 512;
            eventProps.Wnode.Guid          = Guid.NewGuid();
            eventProps.LogFileMode         = EVENT_TRACE_PRIVATE_IN_PROC | EVENT_TRACE_PRIVATE_LOGGER_MODE | EVENT_TRACE_FILE_MODE_SEQUENTIAL;
            eventProps.MaximumFileSize     = 0;
            eventProps.Wnode.Flags         = EtlNativeMethods.WNODE_FLAG_TRACED_GUID;
            eventProps.Wnode.TimeStamp     = 0;
            eventProps.Wnode.ClientContext = 0;
            eventProps.LoggerNameOffset    = (uint)Marshal.SizeOf(typeof(EVENT_TRACE_PROPERTIES));
            eventProps.LogFileNameOffset   = (uint)(Marshal.SizeOf(typeof(EVENT_TRACE_PROPERTIES)) + (sessionName.Length + 1) * 2);

            Marshal.StructureToPtr(eventProps, mem, false);

            int offset = (int)eventProps.LogFileNameOffset;

            for (int i = 0; i < filename.Length; i++, offset += 2)
            {
                Marshal.WriteInt16(mem, offset, filename[i]);
            }
            Marshal.WriteInt16(mem, offset, 0);

            bool success = false;

            try
            {
                ulong handle;
                var   error = EtlNativeMethods.StartTraceW(
                    out handle,
                    sessionName,
                    mem
                    );

                if (error != 0)
                {
                    throw new Win32Exception((int)error);
                }

                var res = new TraceLog(handle, sessionName, mem);
                success = true;
                return(res);
            }
            finally
            {
                if (!success)
                {
                    Marshal.FreeHGlobal(mem);
                }
            }
        }