Click here to Skip to main content
13,451,455 members (45,893 online)
Click here to Skip to main content
Add your own
alternative version


65 bookmarked
Posted 22 Apr 2010


, 29 Apr 2010
Rate this:
Please Sign up or sign in to vote.
Copy files with additional functionalities


Windows Copy just copies the files while the only functionality it provides is cancelling the copy. However there were a few additional functionalities that I required often; they include pausing a copying process, have the files that are not copied list at the end rather than annoying in between.



This application includes the following features:

  • Pause/Resume a copy process
  • Skip a single file
  • Suppress warnings and errors while copying
  • Show list of un-copied files at the end and option to retry copying them
  • Option to suppress overwrite warnings if a file exists.

I have divided the code in two different segments:

  • Copy: deals with copying the files (Project Backup2)
  • User Interface: deals with the User Interface and synchronization with Copy (Project CopyFilesGeneric)

Using the Code

Project Backup2

This is a Library Project. I have used the Shell Function CopyFileEx() to copy the files. This function is defined as:

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern unsafe bool CopyFileEx(string ExistingFileName, string NewFileName, 
CopyProgressRoutine ProgressRoutine, IntPtr Data, ref Boolean Cancel, 
CopyFileFlags CopyFlags);   

Another function HResultToString() converts an HRESULT value to the corresponding message. For this, I have used a file XPSP2CodesEn.csv which stores the HRESULT and their corresponding string message.

public static string HResultToString(uint result)
	System.IO.StreamReader str = 
		new StreamReader(Properties.Resources.ErrorCodeSource);
	LumenWorks.Framework.IO.Csv.CsvReader csv = new CsvReader(str, true);

         csv.SkipEmptyLines = true;
         csv.SupportsMultiline = true;

         foreach (var item in csv)
         	if (uint.Parse(item[0], 
		System.Globalization.CultureInfo.InvariantCulture) == (uint)result)
                 	return item[2];

         return "INVALID HRESULT";

For reading the CSV file, I have used CsvReader by Sebastien Lorion (

The main function CopyFiles() performs the copying operation. It is to be noted that until the files are not counted, it will be useless to start copying. This is because while counting files, the CountFiles() function marks the files to be copied (by adding it to files).

private void CopyFiles()
      if (this.CurrentStatus == CopyStatus.Counting)


      this.CurrentStatus = CopyStatus.Copying;
      foreach (KeyValuePair<string, double> item in files)
      	    bool success = false;
            Boolean b = false;
            previousCopiedSize = 0;
            skip = false;

	    string destinationDirectory = Destination + 
		item.Key.Substring(0, item.Key.LastIndexOf(
                	Path.DirectorySeparatorChar)).Substring(sourceDirectory.Length - 1);
            if (Directory.Exists(item.Key))
                  if ((Directory.CreateDirectory(Destination + 
			item.Key.Substring(sourceDirectory.Length - 1)) == null)) 
                        	unCopiedFiles.Add(new UncopiedFilesStructure(item.Key,
			item.Value, UnsafeNativeMethods.GetHResult(

            if (cancelCopy)

            if (destinationDirectory[destinationDirectory.Length - 1] != 
               		destinationDirectory += Path.DirectorySeparatorChar;

               this.CurrentFile = item.Key;
               RaiseFileCopyStartEvent(item.Key, Path.Combine
		(destinationDirectory, Path.GetFileName(item.Key)), item.Value);

                     success = UnsafeNativeMethods.CopyFileEx(item.Key,
                        destinationDirectory + Path.GetFileName(item.Key),
                        new CopyProgressRoutine(CopyProgressRoutineHandler), IntPtr.Zero,
                        ref b, this.CopyFlags);
               if (!success)
                   string hres = UnsafeNativeMethods.HResultToString

                   if (skip) { unCopiedFiles.Add(new UncopiedFilesStructure
			(item.Key, item.Value, "Skipped: " + hres)); continue; }

                   switch (RaiseFileCopyUnsuccessfulEvent
			(item.Key, destinationDirectory + Path.GetFileName(item.Key),
			 item.Value, hres))
                        case FileHandleProcedure.Skip:
                        case FileHandleProcedure.Cancel:
                            unCopiedFiles.Add(new UncopiedFilesStructure
				(item.Key, item.Value, hres)); break;
                        case FileHandleProcedure.Retry: goto Retry;
                        case FileHandleProcedure.CancelAll: this.cancelCopy = true; break;
                        default: break;
			destinationDirectory + Path.GetFileName(item.Key), item.Value);

        this.CurrentStatus = CopyStatus.CopyCompleted;

Also the user must be notified of a copy failure and dealt with. This task is performed by event FileCopyUnsuccessfull.

Project CopyFile

This project references the Backup2 project and deals with the User Interface and synchronization process.

The most notable function that needs a little explaining is UpdateUI(). This function is defined as:

/// <summary>
/// Synchronize UI with the copying status
/// </summary>
/// <param name="sync">Synchronize Operation To perform</param>
/// <param name="objs">Objects and their values. It must have the following structure:
/// index representation
/// 0. Text; Control whose caption(text) is to be changed
/// 1. the text for control at index 0
/// 2. Status; Text for CopyStatusLabel
/// 3. Status; Text for CurrentFileLabel
/// 4. Progress; the progressbar whose value is to be updated
/// 5. the value of the progressbar specified at index 4
/// 6. UpdateList; Listbox that has to be updated
/// 7. Operation that has to be applied on Listbox at index 6; i.e., ADD, DELETE or CLEAR
/// 8+. objects at index 8 or more are added or deleted from 
/// the listbox at index 6, depending on the operation specified at index 7
/// </param>
private void UpdateUI(SyncronizationOperations sync, object[] objs)
    if ((sync & SyncronizationOperations.CheckBox) == SyncronizationOperations.CheckBox)
    if ((sync & SyncronizationOperations.SetText) == SyncronizationOperations.SetText)
        if (objs.Length > 1 && objs[0] != null && objs[1] != null)
            Control content = objs[0] as Control;
            content.Text = objs[1] as string;
    if ((sync & SyncronizationOperations.SetStatus) == SyncronizationOperations.SetStatus)
        if (objs.Length > 2 && objs[2] != null)
            CopyStatusLabel.Text = objs[2] as string;
            this.Text = CopyStatusLabel.Text;
        if (objs.Length > 3 && objs[3] != null)
            CurrentFileLabel.Text = objs[3] as string;
    if ((sync & SyncronizationOperations.SetProgress) == 
        if (objs.Length > 5 && objs[4] != null && objs[5] != null)
            ProgressBar p = objs[4] as ProgressBar;
            p.Value = Convert.ToInt32(objs[5], CultureInfo.InvariantCulture);
    if ((sync & SyncronizationOperations.UpdateList) == 
        if (objs.Length > 7 && objs[6] != null && objs[7] != null)
            ListView list = objs[6] as ListView;                    
            switch ((ListboxOperations)objs[7])
                case ListboxOperations.ADD:
                    for (int i = 8; i < objs.Length; i++)
                        list.Items.Add(new ListViewItem
				((objs[i] as string).Split('\t')));
                case ListboxOperations.DELETE:
                    for (int i = 8; i < objs.Length; i++)
                        list.Items.Remove(new ListViewItem
				((objs[i] as string).Split('\t')));
                case ListboxOperations.CLEAR:

This code is a really confusing one and needs editing. The thing is I'm new to the concept of threading. This seemed to be the best method I could have came up with. In this method, there are 2 parameters: the first is SyncronizationOperations that defines the operations to be performed; and the second one is an array of objects. The object at index 0 has a control whose text (caption) is to be changed; object at index 1 has the string that has to be assigned to object at index 0. At index 2, we have string that is used to update the overall progress of the copier. Similarly string at index 3 is used to update the name of the current file. Object at index 4 has a progressbar object while that at index 5 has the new value progressbar at index 4. At index 6, we have a listview which is to be updated. The update operations of listview is provide by object (ListboxOperations) and the subsequent elements are the values of listview that are to be operated upon.


  • 23 April 2010 - Initial upload
  • 30 April 2010 - Revision
    • Added Support UI to select files to copy
    • Some other minor changes


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Abhishek Shekhar
India India
No Biography provided

You may also be interested in...

Comments and Discussions

BugVolumeGuid support ? Pin
bindlishankush29-Nov-11 17:33
memberbindlishankush29-Nov-11 17:33 
GeneralProcessing stops at 'CountCompleted' [modified] Pin
IanWithycombe20-Oct-10 9:53
memberIanWithycombe20-Oct-10 9:53 
GeneralThanks for adding the User Interface Pin
Nosa Osayamwen4-May-10 17:53
memberNosa Osayamwen4-May-10 17:53 
GeneralRe: Thanks for adding the User Interface Pin
Abhishek Shekhar4-May-10 21:24
memberAbhishek Shekhar4-May-10 21:24 
GeneralHandle For Paste Pin
eg_Anubhava4-May-10 0:39
membereg_Anubhava4-May-10 0:39 
GeneralRe: Handle For Paste Pin
Abhishek Shekhar4-May-10 17:16
memberAbhishek Shekhar4-May-10 17:16 
GeneralRe: Handle For Paste Pin
eg_Anubhava4-May-10 18:26
membereg_Anubhava4-May-10 18:26 
GeneralRe: Handle For Paste Pin
Abhishek Shekhar4-May-10 21:12
memberAbhishek Shekhar4-May-10 21:12 
GeneralRe: Handle For Paste Pin
eg_Anubhava4-May-10 21:19
membereg_Anubhava4-May-10 21:19 
GeneralRe: Handle For Paste Pin
Abhishek Shekhar4-May-10 21:36
memberAbhishek Shekhar4-May-10 21:36 
GeneralRe: Handle For Paste Pin
eg_Anubhava4-May-10 21:52
membereg_Anubhava4-May-10 21:52 
GeneralRe: Handle For Paste Pin
Abhishek Shekhar4-May-10 22:28
memberAbhishek Shekhar4-May-10 22:28 
GeneralGreat job. Pin
Dinesh Mani30-Apr-10 2:30
memberDinesh Mani30-Apr-10 2:30 
GeneralRe: Great job. Pin
Abhishek Shekhar30-Apr-10 17:52
memberAbhishek Shekhar30-Apr-10 17:52 
GeneralAbout The HResultToString Method Pin
Izzet Kerem Kusmezer30-Apr-10 1:37
memberIzzet Kerem Kusmezer30-Apr-10 1:37 
GeneralRe: About The HResultToString Method Pin
Izzet Kerem Kusmezer30-Apr-10 1:45
memberIzzet Kerem Kusmezer30-Apr-10 1:45 
GeneralRe: About The HResultToString Method Pin
Abhishek Shekhar30-Apr-10 17:42
memberAbhishek Shekhar30-Apr-10 17:42 
QuestionI am Confused Pin
Nosa Osayamwen27-Apr-10 12:17
memberNosa Osayamwen27-Apr-10 12:17 
AnswerRe: I am Confused Pin
Abhishek Shekhar27-Apr-10 17:26
memberAbhishek Shekhar27-Apr-10 17:26 
GeneralRe: I am Confused Pin
Nosa Osayamwen28-Apr-10 11:38
memberNosa Osayamwen28-Apr-10 11:38 
GeneralGood job! Pin
torial23-Apr-10 6:09
membertorial23-Apr-10 6:09 
GeneralRe: Good job! Pin
Abhishek Shekhar23-Apr-10 17:23
memberAbhishek Shekhar23-Apr-10 17:23 
QuestionTeraCopy ? Pin
gpgemini22-Apr-10 21:57
membergpgemini22-Apr-10 21:57 
AnswerRe: TeraCopy ? Pin
jlarini23-Apr-10 3:48
memberjlarini23-Apr-10 3:48 
GeneralRe: TeraCopy ? Pin
gpgemini23-Apr-10 4:13
membergpgemini23-Apr-10 4:13 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01-2016 | 2.8.180318.3 | Last Updated 30 Apr 2010
Article Copyright 2010 by Abhishek Shekhar
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid