.net - Determine whether destination for file move is on same filesystem in C# -


i have windows forms application uses file.move move files in response user request. not asynchronous method, when destination on same drive happens instantly (i assume because can rewrite header , not move anything). however, blocks application if destination not on same drive. not desirable.

so naturally thought switching async. looks way use file streams , use stream.copytoasync before removing original. that's fine, except if is on same drive, lot of wasteful copying.

is there reliable way determine if proposed destination file on different drive drive stored on before deciding operation perform? @ drive letter, seems kind of hacky , think there cases junction points not work correctly.

another possible choice use task.run(() => file.move(x)), although have vaguely bad feeling that.

i think best effort going comparing volume serial numbers. getfileinformationbyhandle() able volume serial number of file handle. ymmv raid / striped volumes, if apply, test solution performance. does work junction points.

the dllimport

[dllimport("kernel32.dll", setlasterror = true)] private static extern bool getfileinformationbyhandle(     intptr hfile,     out by_handle_file_information lpfileinformation); 

we need way suitable file handles use. since we're working potential destinations, if assume destination directory exists, can use createfile() directory handle.

for createfile(), dllimport is

[dllimport("kernel32.dll", charset = charset.auto, setlasterror = true)] private static extern intptr createfile(     [marshalas(unmanagedtype.lptstr)] string filename,     [marshalas(unmanagedtype.u4)] fileaccess access,     [marshalas(unmanagedtype.u4)] fileshare share,     intptr securityattributes,     [marshalas(unmanagedtype.u4)] filemode creationdisposition,     [marshalas(unmanagedtype.u4)] fileattributes flagsandattributes,     intptr templatefile); 

we'll need closehandle(),

[dllimport("kernel32.dll", setlasterror = true)] [reliabilitycontract(consistency.willnotcorruptstate, cer.success)] [suppressunmanagedcodesecurity] [return: marshalas(unmanagedtype.bool)] private static extern bool closehandle(intptr hobject); 

with pieces in place, create wrapper method returns true if volume serial number of supplied paths match. makes sense throw more specific exceptions, sake of brevity:

static bool samevolume(string src, string dest) {     intptr srchandle = intptr.zero, desthandle = intptr.zero;     try     {         srchandle = createfile(src, fileaccess.read, fileshare.readwrite, intptr.zero,             filemode.open, (fileattributes) 0x02000000, intptr.zero);         desthandle = createfile(dest, fileaccess.read, fileshare.readwrite, intptr.zero,             filemode.open, (fileattributes) 0x02000000, intptr.zero);         var srcinfo = new by_handle_file_information();         var destinfo = new by_handle_file_information();          if (!getfileinformationbyhandle(srchandle, out srcinfo))         {             throw new exception(marshal.getlastwin32error().tostring());         }          if (!getfileinformationbyhandle(desthandle, out destinfo))         {             throw new exception(marshal.getlastwin32error().tostring());         }          return srcinfo.volumeserialnumber == destinfo.volumeserialnumber;     }         {         if (srchandle != intptr.zero)         {             closehandle(srchandle);         }          if (desthandle != intptr.zero)         {             closehandle(desthandle);         }     } } 

alternatively, use

task.run(() => file.move(x)) 

or asynchronous construct done without locking application's interface. can't see wrong that.


Comments

Popular posts from this blog

wordpress - (T_ENDFOREACH) php error -

Export Excel workseet into txt file using vba - (text and numbers with formulas) -

Using django-mptt to get only the categories that have items -