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 FileSystemWatcher 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.
I have found a way to track files from an ID from the answer to this stack post. I can successfully grab file IDs based on Approach B in this answer.
While searching I found this stack post stating he found his solution using FSCTL_GET_OBJECT_ID. 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#.
Can anyone give me a push in the right direction for this? I feel like I must be missing something obvious.
Is there a reason C# can't access file/folder IDs? Is tracking files/folders uncommon?
Edit, adding 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 << 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;
}
}
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.)