1
votes

Trying to create a console application to copy directories from the source to the destination and either the progress bar does nothing while files are copied...

My.Computer.FileSystem.CopyDirectory(source, destination)

For i = 1 To 100
    Console.Write(String.Format("Copy progress: {0}%" & vbCr, i))
    Threading.Thread.Sleep(100)
Next

or the ProgressBar says "Copy Progress 1%" the entire time it's copying...

For i = 1 To 100
    Console.Write(String.Format("Copy progress: {0}%" & vbCr, i))
    My.Computer.FileSystem.CopyDirectory(source, destination)
    Threading.Thread.Sleep(100)
Next

Wondering what I am doing wrong because I am obviously putting the My.Computer line in the wrong spot!

2
You will have to copy the files one at a time and increment the progress after each one has copied. The CopyDirectory method does it all before passing control onto the next instruction, so it it not suitable for this purpose. - Andrew Morton
@AndrewMorton Thank You for your response is there something better to use other then CopyDirectory? - bckelley
Once you have obtained a list of the files with the Directory.GetFiles Method you can use the File.Copy Method to copy each one. You may find it the Path.Combine Method useful for putting parts of paths together reliably. - Andrew Morton
@AndrewMorton It says destination is a directory and not a file. - bckelley
You have to tell it the full path to the destination file, including the file name. - Andrew Morton

2 Answers

2
votes

A simple solution, using Linq Select to copy the file list returned by DirectoryInfo.GetFiles()

Pass the sample method an array of Source Directories and a Destination Directory.
The progress (0-100%) is printed to the Output window, and a ProgressBar gives a visual feedback of the copy status for each Source Path.

This method will return the list of all files copied.

enter image description here

Dim sourcePath As String() = New String() {"[SourcePath1]", "[SourcePath2]", "[SourcePath3]"}
Dim destinationPath As String = "[DestinationPath]"
Dim filesCopied As List(Of String) = CopyDirectoryWithProgress(sourcePath, destinationPath)
Console.ReadLine()

Private Function CopyDirectoryWithProgress(sourcePath As String(), destPath As String) As List(Of String)

    Dim allFilesCopied As List(Of String) = New List(Of String)
    Dim progressBarPassSymbol As Char = ChrW(&H25A0)
    Dim progressBarEmptySymbol As String = New String(ChrW(&H2014), 30)

    For Each sPath As String In sourcePath
        Dim fileInfo As New DirectoryInfo(sPath).GetFiles()
        Dim numberOfFiles As Integer = fileInfo.Length - 1
        Dim progressBarPass As Double = (30 / numberOfFiles)
        Dim increment As Double = 100 / numberOfFiles
        Directory.CreateDirectory(destPath)

        Console.CursorLeft = 0
        Console.Write("Copy progress: ")
        Console.CursorLeft = 20
        Console.Write(progressBarEmptySymbol)

        allFilesCopied.AddRange(fileInfo.
            Select(Function(f, i)
               File.Copy(Path.Combine(sPath, f.Name), Path.Combine(destPath, f.Name), True)
               Console.CursorLeft = 15
               Console.Write("{0:g}% " &
                   New String(progressBarPassSymbol, CInt((i + 1) * progressBarPass)),
                   CInt((i + 1) * increment))

               Return f.FullName
           End Function))
        Console.WriteLine()
    Next
    Return allFilesCopied
End Function

For an interesting method to perform this task with a much faster file enumerator, see this CodeProject article: A Faster Directory Enumerator

1
votes

You can invoke the Windows built-in progress bar when copying using the UIOption.AllDialogs:

My.Computer.FileSystem.CopyFile("C:\text.txt", "C:\my_folder\text.txt", FileIO.UIOption.AllDialogs, FileIO.UICancelOption.DoNothing)