Search code examples
c#windowswinapipinvoke

MoveFileWithProgress throws "The system cannot move the file to a different disk drive" – why?


I have:

[SuppressUnmanagedCodeSecurity]
[DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool MoveFileWithProgress(
    string lpExistingFileName, string lpNewFileName,
    CopyProgressRoutine lpProgressRoutine,
    int dwFlags);

public enum MoveFileOptions 
{
    MOVEFILE_COPY_ALLOWED = 0x2
}

And calling it with:

if (!MoveFileWithProgress(source.FullName, destination.FullName, cpr, (int)options)) {
  throw new IOException(new Win32Exception().Message);
}

Where: options is MoveFileOptions.MOVEFILE_COPY_ALLOWED

It works fine when moving in the hard drive. But when I try moving to a Flash-drive, I get: The system cannot move the file to a different disk drive.

Why?


Solution

  • Your DllImport is incorrect. Your function has only 4 parameters, but the real function has 5. Presumably what is happening is that MOVEFILE_COPY_ALLOWED is being passed to lpData and is ignored. The dwFlags parameter is just whatever happens to be sitting on the stack.

    Fixing your p/invoke will probably solve the problem. Also, dwFlags should be unsigned.

    [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    static extern bool MoveFileWithProgress(
        string lpExistingFileName,
        string lpNewFileName,
        CopyProgressRoutine lpProgressRoutine,
        IntPtr lpData,
        uint dwFlags
    );
    

    With this correct you need to decide what to pass to lpData. Since you appear not to be using it at the moment, it doesn't really matter and IntPtr.Zero seems the obvious choice.