Move function

Oct 12, 2010 at 10:55 PM

Firstly, good work. People have been looking for something like this. There was a package called Delimon.Win32.IO which was a fully implemented, but it's website went offline. It was ~900K dll anyway (i have a copy of the dll and source if you want a reference). AlphaFS is too massive for most work. The size of the ZLP dll is excellent - good functionality/size balance.

I did some quick testing before i implement this into my little project (AutoVer). It does everything i need except i can not find a file move or directory move function (which also does renaming). This should be implemented in the IOHelper, FileInfo and DirectoryInfo classes.

I also have a little concern that you are checking the full path for being > 260 chars (MAX_PATH), but the directory portion must also be < 248 chars. It is possible to have a 250 char directory path + 5 char filename and be under the MAX_PATH limit, but still causing a error in the old file functions. Would it be safer to set MAX_PATH to 248 or 250 (248 directory + \ + minimum 1 for file name) just to make sure everything works? You could test both path and file length, but that will take even more cpu cycles.

In terms of what else may be useful, in the FileInfo class, adding the functions to open and create a file stream would be very useful.

Coordinator
Oct 13, 2010 at 5:29 AM

Thanks for your comments and suggestions, I'll put this on my TODO list.

Probably it would be worth checking each function whether it requires a file or folder and set the 248/260 limit accordingly?

Oct 13, 2010 at 5:50 AM

You can do it that way (the proper way). Personally i wouldn't bother - will take some CPU to split the path, not much, but still not worth it for performance reasons if the file functions are called thousands of times per second. Some other projects like Delimon do not check the length at all. They just add the \\?\ prefix regardless (and so the Win32 API has to remove it every time which then takes cpu). I would just apply it if total length is >250 just to keep it simple and fastest possible. Up to you.

Jan 30, 2011 at 10:58 PM
Edited Jan 30, 2011 at 11:06 PM

Someone reminded me of this project today. For everyone's reference, here is the change i made to the code to add MOVE/RENAME ability. I have been successfully using this library for the last few months. Add these code blocks to the 2 files:

PINVOKEHELPER.CS

 

        [DllImport(@"kernel32.dll",
                   CharSet = CharSet.Unicode,
                   CallingConvention = CallingConvention.StdCall,
                   SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool MoveFile(
                           [MarshalAs(UnmanagedType.LPTStr)] string lpExistingFileName,
                           [MarshalAs(UnmanagedType.LPTStr)] string lpNewFileName);

Also change this line:

internal const int MAX_PATH = 260;
to 250

ZLPIOHELPER.CS

        public static void MoveFile(
            string sourceFilePath,
            string destinationFilePath)
        {
            sourceFilePath = CheckAddLongPathPrefix(sourceFilePath);
            destinationFilePath = CheckAddLongPathPrefix(destinationFilePath);

            if (!PInvokeHelper.MoveFile(sourceFilePath, destinationFilePath))
            {
                // http://msdn.microsoft.com/en-us/library/ms681382(VS.85).aspx.

                var lastWin32Error = Marshal.GetLastWin32Error();
                throw new Win32Exception(
                    lastWin32Error,
                    string.Format(
                        "Error {0} moving file '{1}' to '{2}': {3}",
                        lastWin32Error,
                        sourceFilePath,
                        destinationFilePath,
                        CheckAddDotEnd(new Win32Exception(lastWin32Error).Message)));
            }
        }

        public static void MoveDirectory(
            string sourceFilePath,
            string destinationFilePath)
        {
            sourceFilePath = CheckAddLongPathPrefix(sourceFilePath);
            destinationFilePath = CheckAddLongPathPrefix(destinationFilePath);
            //MoveFile also does directories
            if (!PInvokeHelper.MoveFile(sourceFilePath, destinationFilePath))
            {
                // http://msdn.microsoft.com/en-us/library/ms681382(VS.85).aspx.

                var lastWin32Error = Marshal.GetLastWin32Error();
                throw new Win32Exception(
                    lastWin32Error,
                    string.Format(
                        "Error {0} moving directory '{1}' to '{2}': {3}",
                        lastWin32Error,
                        sourceFilePath,
                        destinationFilePath,
                        CheckAddDotEnd(new Win32Exception(lastWin32Error).Message)));
            }
        }

 

Coordinator
Jan 31, 2011 at 4:53 AM

Thank you, bean!

Seems that I did already add this functions and forget to publish them here. I just uploaded a new version.