CopyFileEx shell options

I recently had to switch from using File.Copy() to CopyFileEx , and I'm struggling to find how to use it.

After many searches, I found this beautiful shell to use it, but I need to get the copied bytes of the current file and, if possible, calculate the copy progress of all the files that I transfer to it.

(I know there are projects that have progress indicators related to CopyFileEx , but I am not experienced enough to get the appropriate code, and I would like to use this shell).

Supposedly, simply compare it with the general bytes of the files you want to copy, which I will find in advance, and work out a percentage of this.

My current copy method is

 FileRoutines.CopyFile(new FileInfo("source.txt"), new FileInfo("dest.txt")); 

I am stuck on how to overload it with the parameter needed to get progress information.

 public sealed class FileRoutines { public static void CopyFile(FileInfo source, FileInfo destination) { CopyFile(source, destination, CopyFileOptions.None); } public static void CopyFile(FileInfo source, FileInfo destination, CopyFileOptions options) { CopyFile(source, destination, options, null); } public static void CopyFile(FileInfo source, FileInfo destination, CopyFileOptions options, CopyFileCallback callback) { CopyFile(source, destination, options, callback, null); } public static void CopyFile(FileInfo source, FileInfo destination, CopyFileOptions options, CopyFileCallback callback, object state) { if (source == null) throw new ArgumentNullException("source"); if (destination == null) throw new ArgumentNullException("destination"); if ((options & ~CopyFileOptions.All) != 0) throw new ArgumentOutOfRangeException("options"); new FileIOPermission( FileIOPermissionAccess.Read, source.FullName).Demand(); new FileIOPermission( FileIOPermissionAccess.Write, destination.FullName).Demand(); CopyProgressRoutine cpr = callback == null ? null : new CopyProgressRoutine(new CopyProgressData( source, destination, callback, state).CallbackHandler); bool cancel = false; if (!CopyFileEx(source.FullName, destination.FullName, cpr, IntPtr.Zero, ref cancel, (int)options)) { throw new IOException(new Win32Exception().Message); } } private class CopyProgressData { private FileInfo _source = null; private FileInfo _destination = null; private CopyFileCallback _callback = null; private object _state = null; public CopyProgressData(FileInfo source, FileInfo destination, CopyFileCallback callback, object state) { _source = source; _destination = destination; _callback = callback; _state = state; } public int CallbackHandler( long totalFileSize, long totalBytesTransferred, long streamSize, long streamBytesTransferred, int streamNumber, int callbackReason, IntPtr sourceFile, IntPtr destinationFile, IntPtr data) { return (int)_callback(_source, _destination, _state, totalFileSize, totalBytesTransferred); } } private delegate int CopyProgressRoutine( long totalFileSize, long TotalBytesTransferred, long streamSize, long streamBytesTransferred, int streamNumber, int callbackReason, IntPtr sourceFile, IntPtr destinationFile, IntPtr data); [SuppressUnmanagedCodeSecurity] [DllImport("Kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)] private static extern bool CopyFileEx( string lpExistingFileName, string lpNewFileName, CopyProgressRoutine lpProgressRoutine, IntPtr lpData, ref bool pbCancel, int dwCopyFlags); } public delegate CopyFileCallbackAction CopyFileCallback( FileInfo source, FileInfo destination, object state, long totalFileSize, long totalBytesTransferred); public enum CopyFileCallbackAction { Continue = 0, Cancel = 1, Stop = 2, Quiet = 3 } [Flags] public enum CopyFileOptions { None = 0x0, FailIfDestinationExists = 0x1, Restartable = 0x2, AllowDecryptedDestination = 0x8, All = FailIfDestinationExists | Restartable | AllowDecryptedDestination } 

Any pointers really appreciated.

+6
source share
3 answers

The wrapper already has the plumbing needed to process the progress. Just execute the code to update the progress bar in CallbackHandler before returning. The default value of progressBar1.Maximum is 100, so the code below will calculate the percentage.

Replace the current CopyFile call as follows:

 CopyFileCallbackAction myCallback(FileInfo source, FileInfo destination, object state, long totalFileSize, long totalBytesTransferred) { double dProgress = (totalBytesTransferred / (double)totalFileSize) * 100.0; progressBar1.Value = (int)dProgress; return CopyFileCallbackAction.Continue; } FileRoutines.CopyFile(new FileInfo("source.txt"), new FileInfo("dest.txt"), myCallback); 
+8
source

If you just want to show a progress bar for a copy of the file, you can do this . It uses the standard Windows dialog box, which shows the progress bar and the remaining time, and has a Cancel button. This was exactly what I needed in basically one line of code.

 // The following using directive requires a project reference to Microsoft.VisualBasic. using Microsoft.VisualBasic.FileIO; class FileProgress { static void Main() { // Specify the path to a folder that you want to copy. If the folder is small, // you won't have time to see the progress dialog box. string sourcePath = @"C:\Windows\symbols\"; // Choose a destination for the copied files. string destinationPath = @"C:\TestFolder"; FileSystem.CopyDirectory(sourcePath, destinationPath, UIOption.AllDialogs); } } 
0
source

I added this to copy all the files in the directory, in case the poster is interested in using progressBar based on all the files being copied.

  private void button1_Click(object sender, EventArgs e) { string[] fileNames = Directory.GetFiles(Application.StartupPath + @"\SourceFolder\", "*.*"); long bytes = GetTransferSize(fileNames); foreach (string name in fileNames) { FileRoutines.CopyFile(new FileInfo(name), new FileInfo(Application.StartupPath + @"\DestFolder\" + Path.GetFileName(name)), CopyFileOptions.None, myCallback); } } static long GetTransferSize(string[] fileNames) { long size = 0; // Calculate total size by looping through files in the folder and totalling their sizes foreach (string name in fileNames) { // length of each file. FileInfo details = new FileInfo(name); size += details.Length; } return size; } 
0
source

All Articles