Skip to content

Instantly share code, notes, and snippets.

@mfcollins3
Created June 29, 2013 06:03
Show Gist options
  • Save mfcollins3/5890044 to your computer and use it in GitHub Desktop.
Save mfcollins3/5890044 to your computer and use it in GitHub Desktop.
Process Monitor is a great tool for finding and solving problems with programs in production environments. Along with the usual events that Process Monitor captures and logs, Process Monitor allows developers to send log messages to be included in the log so that process events can be correlated to program source code. This Gist contains the sou…

Outputting Trace Information to Process Monitor

This Gist shows how to output trace messages to Process Monitor at runtime. Writing trace messages to Process Monitor will let you see how process events correlate to parts of your program.

Using the ProcessMonitor class is fairly easy. For example, the following program outputs three trace messages to Process Monitor:

internal class Program
{
    private void Main()
    {
        using (var procmon = new ProcessMonitor())
        {
            procmon.WriteMessage("The program is starting.");
            Thread.Sleep(5000);
            procmon.WriteMessage("The program is running.");
            Thread.Sleep(5000);
            procmon.WriteMessage("The program is ending.");
        }
    }
}

In order to see the trace messages in the Process Monitor log, you must enable profiling events. If you do not enable profiling events, the events will still be captured and added to the log, but the events will be filtered out from being displayed in the Process Monitor viewer.

internal static class NativeMethods
{
[DllImport("kernel32.dll", CallingConvention = CallingConvention.WinApi,
EntryPoint = "CloseHandle", ExactSpelling = true, SetLastError = true)]
internal static extern bool CloseHandle(IntPtr handle);
[DllImport("kernel32.dll", CallingConvention = CallingConvention.WinApi,
CharSet = CharSet.Unicode, EntryPoint = "CreateFileW",
ExactSpelling = true, SetLastError = true)]
internal static extern IntPtr CreateFile(
string fileName,
uint desiredAccess,
uint shareMode,
IntPtr securityAttributes,
uint creationDisposition,
uint flagsAndAttributes,
IntPtr templateFile);
[DllImport("kernel32.dll", CallingConvention = CallingConvention.WinApi,
EntryPoint = "DeviceIoControl", ExactSpelling = true, SetLastError = true)]
internal static extern bool DeviceIoControl(
IntPtr handle,
uint ioControlCode,
IntPtr inBuffer,
uint inBufferSize,
IntPtr outBuffer,
uint outBufferSize,
out uint bytesReturned,
IntPtr overlapped);
}
public class ProcessMonitor : IDisposable
{
private const uint IoControlCode = (0x9535U << 16) | (0x2U << 14) | (0x81U << 2);
private static readonly IntPtr InvalidHandleValue = new IntPtr(-1);
private readonly IntPtr handle;
private bool disposed;
public ProcessMonitor()
{
this.handle = NativeMethods.CreateFile(
"\\\\.\\Global\\ProcmonDebugLogger",
0xC0000000U,
7U,
IntPtr.Zero,
3U,
0x80U,
IntPtr.Zero);
if (InvalidHandleValue != this.handle)
{
return;
}
var errorMessage = string.Format(
CultureInfo.CurrentCulture,
"CreateFile returned {0}",
Marshal.GetLastWin32Error());
throw new Exception(errorMessage);
}
~ProcessMonitor()
{
this.Dispose(false);
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
public void WriteMessage(string message)
{
var buffer = IntPtr.Zero;
try
{
buffer = Marshal.StringToHGlobalUni(message);
uint bytesWritten;
var inBufferSize = Convert.ToUInt32(Math.Min(4096, message.Length * 2));
var succeeded = NativeMethods.DeviceIoControl(
this.handle,
IoControlCode,
buffer,
inBufferSize,
IntPtr.Zero,
0,
out bytesWritten,
IntPtr.Zero);
if (succeeded)
{
return;
}
var errorMessage = string.Format(
CultureInfo.CurrentCulture,
"DeviceIoControl returned {0}",
Marshal.GetLastWin32Error());
throw new Exception(errorMessage);
}
finally
{
if (IntPtr.Zero != buffer)
{
Marshal.FreeHGlobal(buffer);
}
}
}
public void WriteMessage(
IFormatProvider formatProvider,
string format,
params object[] args)
{
var message = string.Format(formatProvider, format, args);
this.WriteMessage(message);
}
protected virtual void Dispose(bool disposing)
{
if (this.disposed)
{
return;
}
if (!NativeMethods.CloseHandle(this.handle))
{
var message = string.Format(
CultureInfo.CurrentCulture,
"CloseHandle returned {0}",
Marshal.GetLastWin32Error());
throw new Exception(message);
}
if (!disposing)
{
return;
}
this.disposed = true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment