title: How can I log low-level OS file transactions in C#?
body: <p>Since File/Process Monitor falls short in terms of filtering and <a href="https://superuser.com/questions/1380088/removing-near-duplicate-rows-in-filemon-process-monitor-to-more-easily-analyze">unnecessary duplication when logging</a>, I want to recreate what that program does and log all Windows file operations live in realtime.</p>
  
  <p>I want to record various attributes such as the time, process name, source path, destination path, operation, result, and detail, just like <a href="https://i.stack.imgur.com/xLooE.png" rel="nofollow noreferrer">Process Monitor does</a>.</p>
  
  <p>How can I get C# to extract this information from the OS?</p>
  
  <hr>
  
  <p>EDIT: As zett42 pointed out, the <code>FileSystemWatcher</code> won't quite work as for example, file events created from processes themselves won't be intercepted. For instance, none of <a href="https://i.imgur.com/T64ArkT.png" rel="nofollow noreferrer">these transactions</a> show up, even though I added the events: <code>Changed</code>, <code>Created</code>, <code>Renamed</code>, and <code>Deleted</code> to the <code>FileSystemWatcher</code> and set the <code>EnableRaisingEvents</code> flag to true.</p>
  
  <hr>
  
  <p>EDIT 2: Using SimonMourier's suggestion of the  Microsoft.Diagnostics.Tracing.TraceEvent nuget package, I managed to knock up the code below.</p>
  
  <p>This section is put into a background worker:</p>
  
  <pre><code>Console.CancelKeyPress += (sender, e) =&gt; session.Stop();
  session.EnableKernelProvider(KernelTraceEventParser.Keywords.All);
  session.Source.Kernel.FileIOWrite += Kernel_FileIOWrite;            
  session.Source.Process();
  </code></pre>
  
  <p>And then the FileIOWrite event created runs the following when called (automatically):</p>
  
  <pre><code>private void Kernel_FileIOWrite(Microsoft.Diagnostics.Tracing.Parsers.Kernel.FileIOReadWriteTraceData obj)
  {
      string filename = obj.FileName;
      string processpath = "";
      if (obj.ProcessID == 0) processpath = "System Idle Process";
      else if (obj.ProcessID == 4) processpath = "System";
      else
      {
          try { processpath = "ID: " + obj.ProcessID + ": "+ Process.GetProcessById(obj.ProcessID).MainModule.FileName; }
          catch { processpath = "error ID: "+ obj.ProcessID; }
      }
      richTextBox1.AppendText(filename + " ............."+ processpath +"\n");
  }
  </code></pre>
  
  <p>Unfortunately, <code>FileIOReadWriteTraceData.FileName</code> is not picking up things Procmon picks up such as (for example), very common Chrome stuff such as writing to <code>C:\Users\Dan\AppData\Local\Google\Chrome\User Data\Default\Cookies-journal</code> or <code>C:\Users\Dan\AppData\Local\Google\Chrome\User Data\Default\Current Session</code></p>