i trying track files , folders through lifetime (they may moved or renamed). have done searching , found filesystemwatcher might popular way track files , folders, however, not work me application may or may not running. have chosen try track folders via id.
i have found way track files id answer this stack post. can grab file ids based on approach b in this answer.
while searching found this stack post stating found solution using fsctl_get_object_id. have spent quite bit of time trying figure out how use function, can not wrap head around it. have 0 experience calling native windows functions within c#.
can give me push in right direction this? feel must missing obvious.
is there reason c# can't access file/folder ids? tracking files/folders uncommon?
edit, adding code:
static uint returnval; //working example 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 handle on 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 returning id 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 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 getting error "87" deviceiocontrol, invalid parameter according post on msdn (i unable post more links due reputation restrictions.)
seems got no problem filesystemwatcher
. so, how use deviceiocontrol
in c#, have of answer:
physical disk size not correct (ioctldiskgetdrivegeometry)
to question, it's done following code:
class program { const uint fsctl_get_object_id=0x0009009c; public static string getfileid(string path) { using(var fs=file.open( path, filemode.openorcreate, fileaccess.readwrite, fileshare.readwrite) ) { winapi.by_handle_file_information info; winapi.getfileinformationbyhandle(fs.handle, out info); return string.format( "{0:x}", ((info.fileindexhigh<<32)|info.fileindexlow)); } } public static winapi.file_objectid_buffer getfolderidbuffer(string path) { using(var hfile=winapi.createfile( path, winapi.generic_read, fileshare.read, intptr.zero, (filemode)winapi.open_existing, winapi.file_flag_backup_semantics, intptr.zero )) { if(null==hfile||hfile.isinvalid) throw new win32exception(marshal.getlastwin32error()); var buffer=default(winapi.file_objectid_buffer); var noutbuffersize=marshal.sizeof(buffer); var lpoutbuffer=marshal.allochglobal(noutbuffersize); var lpbytesreturned=default(uint); var result= winapi.deviceiocontrol( hfile, fsctl_get_object_id, intptr.zero, 0, lpoutbuffer, noutbuffersize, ref lpbytesreturned, intptr.zero ); if(!result) throw new win32exception(marshal.getlastwin32error()); var type=typeof(winapi.file_objectid_buffer); buffer=(winapi.file_objectid_buffer) marshal.ptrtostructure(lpoutbuffer, type); marshal.freehglobal(lpoutbuffer); return buffer; } } public static void main(string[] args) { console.writeline( getfileid(@"c:\users\matt\desktop\testdocument.txt")); var buffer=getfolderidbuffer(@"c:\users\matt\desktop"); var objectid=buffer.objectid .reverse() .select(x => x.tostring("x2")) .aggregate(string.concat); console.writeline("{0}", objectid); } } class winapi { internal const int generic_read=unchecked((int)0x80000000), file_flag_backup_semantics=unchecked((int)0x02000000), open_existing=unchecked((int)3); [structlayout(layoutkind.sequential)] public struct file_objectid_buffer { public struct union { [marshalas(unmanagedtype.byvalarray, sizeconst=16)] public byte[] birthvolumeid; [marshalas(unmanagedtype.byvalarray, sizeconst=16)] public byte[] birthobjectid; [marshalas(unmanagedtype.byvalarray, sizeconst=16)] public byte[] domainid; } [marshalas(unmanagedtype.byvalarray, sizeconst=16)] public byte[] objectid; public union birthinfo; [marshalas(unmanagedtype.byvalarray, sizeconst=48)] public byte[] extendedinfo; } [structlayout(layoutkind.sequential)] 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; } [dllimport("kernel32.dll", setlasterror=true)] public static extern bool deviceiocontrol( safefilehandle hdevice, uint dwiocontrolcode, intptr lpinbuffer, uint ninbuffersize, [out] intptr lpoutbuffer, int noutbuffersize, ref uint lpbytesreturned, intptr lpoverlapped ); [dllimport("kernel32.dll", setlasterror=true)] public static extern safefilehandle createfile( string filename, int dwdesiredaccess, system.io.fileshare dwsharemode, intptr securityattrs_mustbezero, system.io.filemode dwcreationdisposition, int dwflagsandattributes, intptr htemplatefile_mustbezero ); [dllimport("kernel32.dll", setlasterror=true)] public static extern bool getfileinformationbyhandle( intptr hfile, out by_handle_file_information lpfileinformation); }
the name space required of using:
using microsoft.win32.safehandles;
Comments
Post a Comment