title: Getting a Folder ID C#
body: <p>I am trying to track a files and folders through their lifetime (they may be moved or renamed). I have done searching and found that <a href="http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx" rel="nofollow noreferrer">FileSystemWatcher</a> might be the most popular way to track files and folders, however, this will not work for me as the application may or may not be always running. I have chosen to try to track the folders via an ID.</p>
  
  <p>I have found a way to track files from an ID from the answer to <a href="https://stackoverflow.com/a/1866547/2352808">this stack post</a>. I can successfully grab file IDs based on Approach B in <a href="https://stackoverflow.com/a/1866788/2352808">this answer</a>.</p>
  
  <p>While searching I found <a href="https://stackoverflow.com/q/10132686/2352808">this stack post</a> stating he found his solution using <a href="http://msdn.microsoft.com/en-ca/library/windows/desktop/aa364570%28v=vs.85%29.aspx" rel="nofollow noreferrer">FSCTL_GET_OBJECT_ID</a>. I have spent quite a bit of time trying to figure out how to use this function, but I can not wrap my head around it. I have essentially zero experience calling native windows functions from within C#.</p>
  
  <p>Can anyone give me a push in the right direction for this? I feel like I must be missing something obvious. </p>
  
  <p>Is there a reason C# can't access file/folder IDs? Is tracking files/folders uncommon?</p>
  
  <p>Edit, adding code:</p>
  
  <pre><code>        static uint returnVal;
  
      //Working example to get File ID
      public static string GetFileId(string path)
      {
          WinAPI.BY_HANDLE_FILE_INFORMATION objectFileInfo = new WinAPI.BY_HANDLE_FILE_INFORMATION();
  
          FileInfo fi = new FileInfo(path);
          FileStream fs = fi.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
  
          WinAPI.GetFileInformationByHandle(fs.Handle, out objectFileInfo);
  
          fs.Close();
  
          ulong fileIndex = ((ulong)objectFileInfo.FileIndexHigh &lt;&lt; 32) + (ulong)objectFileInfo.FileIndexLow;
  
          return fileIndex.ToString();
      }
  
      public static string GetFolderId(string path)
      {
          //Get a handle on the given folder
          IntPtr cFile = WinAPI.CreateFile(
              path,
              WinAPI.GENERIC_READ,
              FileShare.Read,
              IntPtr.Zero,
              (FileMode)WinAPI.OPEN_EXISTING,
              WinAPI.FILE_FLAG_BACKUP_SEMANTICS,
              IntPtr.Zero);
  
          Console.WriteLine(path);
          Console.WriteLine(cFile);
  
          if ((int)cFile != -1)
          {
              int cFileSize = Marshal.SizeOf(typeof(IntPtr));
              Console.WriteLine("cFile size = {0}", cFileSize);
  
              IntPtr cFileBlob = Marshal.AllocHGlobal(cFileSize);
              uint numBytesRead = 0;
  
              WinAPI.DeviceIoControl(cFile, WinAPI.FSCTL_GET_OBJECT_ID, IntPtr.Zero, 0, cFileBlob, (uint)cFileSize, ref numBytesRead, IntPtr.Zero);
  
              if (returnVal == 0)
              {
                  Console.WriteLine(Marshal.GetLastWin32Error()); // Returning error 87 here
              }
          }
  
          //Should be returning the ID from the folder.
          return String.Empty;
      }
  
      public static void Main(string[] args)
      {
      Console.WriteLine(GetFileId(@"C:\Users\Matt\Desktop\TestDocument.txt"));
      Console.WriteLine(GetFolderId(@"C:\Users\Matt\Desktop"));
      }
  
  }
  
  class WinAPI
  {
      // Win32 constants for accessing files.
      internal const int GENERIC_READ = unchecked((int)0x80000000);
      internal const int FILE_FLAG_BACKUP_SEMANTICS = unchecked((int)0x02000000);
      internal const int OPEN_EXISTING = unchecked((int)3);
      internal const int FSCTL_GET_OBJECT_ID = 0x0009009c;
      internal const int FSCTL_CREATE_OR_GET_OBJECT_ID = 0x000900c0;
  
      [DllImport("kernel32.dll", SetLastError = true)]
      public static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize, [Out] IntPtr lpOutBuffer, uint nOutBufferSize, ref uint lpBytesReturned, IntPtr lpOverlapped);
  
      [DllImport("kernel32.dll", SetLastError = true)]
      public static extern bool GetFileInformationByHandle(IntPtr hFile, out BY_HANDLE_FILE_INFORMATION lpFileInformation);
  
      [DllImport("kernel32.dll", SetLastError = true)]
      public static extern IntPtr CreateFile(
         String fileName,
         int dwDesiredAccess,
         System.IO.FileShare dwShareMode,
         IntPtr securityAttrs_MustBeZero,
         System.IO.FileMode dwCreationDisposition,
         int dwFlagsAndAttributes,
         IntPtr hTemplateFile_MustBeZero);
  
      public struct BY_HANDLE_FILE_INFORMATION
      {
          public uint FileAttributes;
          public FILETIME CreationTime;
          public FILETIME LastAccessTime;
          public FILETIME LastWriteTime;
          public uint VolumeSerialNumber;
          public uint FileSizeHigh;
          public uint FileSizeLow;
          public uint NumberOfLinks;
          public uint FileIndexHigh;
          public uint FileIndexLow;
      }
  }
  </code></pre>
  
  <p>I am getting the error "87" back from DeviceIoControl, which is invalid parameter according to a post on MSDN (I am unable to post more links due to reputation restrictions.)</p>