Search code examples
c#winapifile-copying

What is wrong with my WINAPI call to handle long file paths?


I've been trying to figure out the best way to copy files in Windows with deep paths (files, not folders so robocopy is out of the question). The best solution I've been able to come up with is writing my own solution. I've been able to write the code to handle listing directories with 10,000 character deeps paths but using the same approach doesn't seem to be working for actually copying files. I tired using the System.IO libraries with \?\ prefixed to paths and that didn't seem to work.

[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CopyFile(string lpExistingFileName, string lpNewFileName,
   bool bFailIfExists);

public static bool CopyFile(string source, string dest)
{
    source = fixPathForLong(source);
    dest = fixPathForLong(dest);

    return CopyFile(source, dest, false);
}

private static string fixPathForLong(String path)
{
    if (!path.StartsWith(@"\\?\"))
        path = @"\\?\" + path;
    return path;
}

Solution

  • If the call to CopyFile (not your overload, the P/Invoke declaration) returns false I would throw a Win32Exception:

    public static void CopyFile(string source, string dest)
    {
        source = fixPathForLong(source);
        dest = fixPathForLong(dest);
    
        if (!CopyFile(source, dest, false))
        {
            throw new Win32Exception();
        }
    }
    

    The default constructor for the Win32Exception class will make a call to GetLastError and give you more detailed error information as to why the operation failed.