שתף באמצעות


Copy a Directory with a progress bar

Question

Thursday, September 24, 2015 10:51 AM

Hi,

I need to copy a directory from one place to another. So I have used the following code to do that.

My.Computer.FileSystem.CopyDirectory(var_originfilepath, var_copypath, True)

So this time I need to activate a progress bar when this directory is copying. I can do this for a single file with IO.filestream procedure. But this time I need to do with a directory. My directory capacity is less than 10MB. Can I do these things in this way or is there a any other solution. I like to know that. But don't forget I have beginner skills with Microsoft visual basic 2008.

(I'm using .net framework 2.0. You can checkout my interface with attachment.)

 

All replies (24)

Saturday, September 26, 2015 6:51 PM ✅Answered | 1 vote

Hi Frank !!

As you said I can use .net framework 3.5 with VS2008. I think there is no way to do my job with .net framework 2.0. I have tried the above code that Mr. Monkeyboy replied to me. But it's not the solution for me yet. The reason is that code doesn't works with folders whether there are sub folders. So can you show me another way to do my job with following code and background worker.

My.Computer.FileSystem.CopyDirectory(var_originfilepath, var_copypath, True)

Thanks in Advance !!

As promised, here's the link to the project folder which is on my website:

http://www.fls-online.com/VBNet_Forum/09-26-15/SimpleFileAndDirectoryCopy.zip

When you download and extract that then open it in your version of Visual Studio, it will ask you to convert it. Just follow the prompts and it should work ok. It's set up for framework 3.5. If you have a problem with it, then let me know and I'll redo it in VS2008, but I created it with VS2010. I'm hoping it'll convert.

Even if it doesn't though, you don't really want my lousy user interface; I just used that to test with really. It's the class behind it that's the workhorse here and I'll get into that shortly.

Use the code for the UI that I'll show momentarily to give you an idea about what does what.

*****

In one way or another, I've "done this to death". Not this specifically, but similar things so I used a fair amount from earlier works that I've done.

The solution has two projects in it:

The one that I show above highlighted is a namespace that has the "engine" in it and the code for it is shown on a page of my website here. If you copy from that, click the link shown at the top of the page and copy the unformatted text version of it, but hopefully everything will convert without issue.

One of the things that I have in here is this: If the target path exists, then it's quite possible that copying isn't necessary. If it exists, the code in that class tests to see if the two files' sizes are the same and, if so, if the two files' last write date/times are the same. If they are, then obviously there's no reason to overwrite it and that will be shown momentarily when I run it, then cancel it, then run it again using the same paths for source and target.

*****

I'll step through how I have the UI set up, but I encourage you to use your own ... this is a really simple-simon deal that I put together mainly just to test it:

Now I'll cancel it:

When I re-select the same source and target directories (and choose the same method to copy: Copy all subdirectories), it will "pick up where it left off" because it doesn't need to copy those first ones now:

The code for the UI follows (note the methods and events that come from the class - that's what your code needs to use):

Option Strict On
Option Explicit On
Option Infer Off

Imports DirectoryCopy = FileOperations.FileAndDirectoryCopy

Public Class Form1
    Private WithEvents copier As DirectoryCopy.Copy

    Private _sourceDirectory As String
    Private _targetDirectory As String

    Private Sub Form1_Load(sender As System.Object, _
                           e As System.EventArgs) _
                           Handles MyBase.Load

        With ProgressBar1
            .Minimum = 0
            .Maximum = 100
            .Visible = False
        End With

        lbl_SourceFolder.Text = "Not Selected"
        lbl_TargetFolder.Text = "Not Selected"

        lbl_CurrentStatus.Text = "--"
        lbl_Operation.Text = "--"
        lbl_TotalDirectoryCount.Text = "--"
        lbl_TotalFileCount.Text = "--"

        lbl_StatusLeft.Text = ""

        btn_Cancel.Enabled = False
        GroupBox_Copy.Enabled = False

    End Sub

    Private Sub _
        btn_BrowseToSource_Click(sender As System.Object, _
                                 e As System.EventArgs) _
                                 Handles btn_BrowseToSource.Click

        _sourceDirectory = Nothing
        lbl_SourceFolder.Text = "Not Selected"

        Using fbd As New FolderBrowserDialog
            With fbd
                .Description = "Select The Directory To Copy FROM"
                .RootFolder = Environment.SpecialFolder.MyComputer
                .ShowNewFolderButton = False
            End With

            If fbd.ShowDialog = Windows.Forms.DialogResult.OK Then
                _sourceDirectory = fbd.SelectedPath
                lbl_SourceFolder.Text = fbd.SelectedPath
            End If
        End Using

        CheckOkToCopy()

    End Sub

    Private Sub _
        btn_BrowseToTarget_Click(sender As System.Object, _
                                 e As System.EventArgs) _
                                 Handles btn_BrowseToTarget.Click

        _targetDirectory = Nothing
        lbl_TargetFolder.Text = "Not Selected"

        Using fbd As New FolderBrowserDialog
            With fbd
                .Description = "Select The Directory To Copy TO"
                .RootFolder = Environment.SpecialFolder.MyComputer
                .ShowNewFolderButton = True
            End With

            If fbd.ShowDialog = Windows.Forms.DialogResult.OK Then
                _targetDirectory = fbd.SelectedPath
                lbl_TargetFolder.Text = fbd.SelectedPath
            End If
        End Using

        CheckOkToCopy()

    End Sub

    Private Sub RadioButton_Click(sender As Object, _
                                  e As System.EventArgs) Handles _
                                  RadioButton_RootOnly.Click, _
                                  RadioButton_RootAndSubfolders.Click

        CheckOkToCopy()

    End Sub

    Private Sub CheckOkToCopy()

        If Not String.IsNullOrEmpty(_sourceDirectory) AndAlso _
            IO.Directory.Exists(_sourceDirectory) AndAlso _
            Not String.IsNullOrEmpty(_targetDirectory) AndAlso _
            IO.Directory.Exists(_targetDirectory) AndAlso _
            (RadioButton_RootOnly.Checked OrElse RadioButton_RootAndSubfolders.Checked) Then

            If New IO.DirectoryInfo(_sourceDirectory).FullName = New IO.DirectoryInfo(_targetDirectory).FullName Then
                MessageBox.Show("The source and target directories cannot be the same.", _
                                "Source And Target Are Identical", _
                                MessageBoxButtons.OK, _
                                MessageBoxIcon.Warning)

                GroupBox_Copy.Enabled = False
            Else
                GroupBox_Copy.Enabled = True
            End If
        Else
            GroupBox_Copy.Enabled = False
        End If

    End Sub





#Region "Copy Directories And Files"

    Private Sub _
      btn_Begin_Click(sender As System.Object, _
                      e As System.EventArgs) _
                      Handles btn_Begin.Click

        btn_Begin.Enabled = False
        btn_Cancel.Enabled = True
        btn_BrowseToSource.Enabled = False
        btn_BrowseToTarget.Enabled = False
        RadioButton_RootOnly.Enabled = False
        RadioButton_RootAndSubfolders.Enabled = False

        Me.Refresh()

        copier = New DirectoryCopy.Copy

        If RadioButton_RootOnly.Checked Then
            copier.BeginOperation(_sourceDirectory, _
                                  _targetDirectory, _
                                  FileOperations.FileAndDirectoryCopy.Copy.DirectoryParsing.TopLevelOnly)
        Else
            copier.BeginOperation(_sourceDirectory, _
                                 _targetDirectory, _
                                 FileOperations.FileAndDirectoryCopy.Copy.DirectoryParsing.IncludeSubfolders)
        End If

    End Sub

    Private Sub _
        btn_Cancel_Click(sender As System.Object, _
                         e As System.EventArgs) _
                         Handles btn_Cancel.Click

        copier.CancelOperation()

        With btn_Cancel
            .Enabled = False
            .Refresh()
        End With

    End Sub

    Private Sub _
        copier_ProgressChanged(sender As Object, _
                               e As FileOperations.FileAndDirectoryCopy.Copy.ProgressChangedEventArgs) _
                               Handles copier.ProgressChanged

        If e.UserCancelledOperation Then
            lbl_Operation.Text = "Cancelling Operation..."
        Else
            lbl_Operation.Text = e.CurrentActivity_String

            Select Case e.CurrentActivity
                Case FileOperations.FileAndDirectoryCopy.Copy.OperationType.Copying
                    lbl_CurrentStatus.Text = _
                        String.Format("Copied {0} of {1} Files ({2} of {3}){4}{5} Completed", _
                                      e.CurrentFileCount_String, _
                                      e.TotalFileCount_String, _
                                      e.CumulativeFileSize_String, _
                                      e.TotalFilesSize_String, _
                                      vbCrLf, _
                                      e.CurrentProgress_String(1))

                    lbl_TotalDirectoryCount.Text = e.TotalDirectoryCount_String

                    lbl_TotalFileCount.Text = _
                        String.Format("{0} ({1})", _
                                      e.TotalFileCount_String, _
                                      e.TotalFilesSize_String)

                    If e.CurrentProgressForProgressBar > 0 Then
                        With ProgressBar1
                            .Visible = True
                            .Value = e.CurrentProgressForProgressBar
                            .Refresh()
                        End With
                    End If

                Case Else
                    lbl_CurrentStatus.Text = "--"
                    lbl_TotalDirectoryCount.Text = "--"
                    lbl_TotalFileCount.Text = "--"
            End Select
        End If

        lbl_StatusLeft.Text = "Elapsed: " & e.Elapsed_String

    End Sub

    Private Sub _
        copier_OperationComplete(sender As Object, _
                                 e As FileOperations.FileAndDirectoryCopy.Copy.OperationCompleteEventArgs) _
                                 Handles copier.OperationComplete

        With ProgressBar1
            .Visible = False
            .Value = 0
        End With

        _sourceDirectory = Nothing
        _targetDirectory = Nothing

        lbl_SourceFolder.Text = "Not Selected"
        lbl_TargetFolder.Text = "Not Selected"

        lbl_CurrentStatus.Text = "--"
        lbl_Operation.Text = "--"
        lbl_TotalDirectoryCount.Text = "--"
        lbl_TotalFileCount.Text = "--"

        btn_Cancel.Enabled = False
        btn_Begin.Enabled = True
        GroupBox_Copy.Enabled = False

        CheckOkToCopy()

        If e.OperationException IsNot Nothing Then
            MessageBox.Show(String.Format("An error occurred:{0}{0}{1}", _
                                          vbCrLf, e.OperationException.Message), _
                                          "Exception Thrown", _
                                          MessageBoxButtons.OK, _
                                          MessageBoxIcon.Warning)

        ElseIf e.UserCancelledOperation Then
            lbl_Operation.Text = "Operation Cancelled"
            btn_BrowseToSource.Enabled = True
            btn_BrowseToTarget.Enabled = True
            RadioButton_RootOnly.Enabled = True
            RadioButton_RootAndSubfolders.Enabled = True

        Else
            lbl_Operation.Text = "All Files And Directories Copied"
        End If

    End Sub
#End Region

End Class

Give that a go and let me know how you fare. :)

"I never failed once... It just happened to be a 2000-step process." -- Thomas Edison


Saturday, September 26, 2015 9:18 PM ✅Answered | 1 vote

As an addendum, this zip file now has both versions, including a folder which was set up using VS2008:

The assembly with the class library is identical; in fact I simply used the very same one:

So hopefully now you won't have any problems using this. :)

"I never failed once... It just happened to be a 2000-step process." -- Thomas Edison


Thursday, September 24, 2015 12:33 PM | 3 votes

The code below:

        Dim var_originfilepath As String = "D:\Prog-ram Files"
        Dim var_copypath As String = "D:\Prog-ram FilesBackup"
        My.Computer.FileSystem.CopyDirectory(var_originfilepath, var_copypath, UIOption.AllDialogs, UICancelOption.DoNothing)

Yields this on screen:

You need this also:

Imports Microsoft.VisualBasic.FileIO

I believe Vista or higher is required, you could also write your own method, first enumerate all files, then copy each file and update your progress bar with either how many files were copied versus how many total files, or get the total of all file sizes and keep a running total of how many bytes have been copied.


Thursday, September 24, 2015 12:56 PM

Hello Devon Nullman,

I'm appreciate your reply for me. Actually I have tried this method, but it's doesn't suit for me. So I have found another piece of code and tried it too. It's works fine.

    Private Sub btncopy_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btncopy.Click

        Dim var_originfilepath As New DirectoryInfo("D:\M06 - Perform Internet & Email Operations\)
        Dim var_copypath As String = fbd.SelectedPath & "\ & "001"

        'My.Computer.FileSystem.CopyDirectory(var_originfilepath, fbd.SelectedPath & "\ & "001", True)

        If fbd.ShowDialog = Windows.Forms.DialogResult.OK Then
            Dim desFolder As DirectoryInfo
            If IO.Directory.Exists(fbd.SelectedPath & "\ & var_originfilepath.Name) Then
                desFolder = New DirectoryInfo(fbd.SelectedPath & "\ & var_originfilepath.Name)
            Else
                'Create the same name folder under the choosed destination folder  
                desFolder = Directory.CreateDirectory(fbd.SelectedPath & "\ & var_originfilepath.Name)
            End If

            pbar.Maximum = var_originfilepath.GetFiles("*", SearchOption.AllDirectories).Length

            'Copy each file  
            For Each file As FileInfo In var_originfilepath.GetFiles("*", SearchOption.AllDirectories)
                IO.File.Copy(file.FullName, desFolder.FullName & "\ & file.Name, True)
                pbar.Value += 1
                Application.DoEvents()
            Next

        End If

This piece of code has a tiny problem. All things are work fine and all files were copied successfully with my progress bar. So I tried to copy a folder with sub folders and file. So when I copy this folder to my destination I have the main folder and included files. But the problem is this piece of code doesn't create my sub folders as well as like source folder. Can you improve this piece of code for me? If we can clear this problem in this code, it will be the solution for my problem.

Thanks in Advance !!


Saturday, September 26, 2015 4:28 AM

Hello

I have developed the above code for copy two of sub directories in one directory. This code works fine but it's not the efficient way to do this. If anyone can improve this code with loops or any other way this will helps more people to copy a directory with their own way.

(You need one button and one progress bar)

Imports System.IO

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim sourceFolder1 As New DirectoryInfo("F:\C++ Projects\123")
        Dim sourceFolder2 As New DirectoryInfo("F:\C++ Projects\Videos")

        'FolderBrowserDialog1 is used to choose destination folder  
        Dim FolderBrowserDialog1 As New FolderBrowserDialog

        If FolderBrowserDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
            Dim desFolder As DirectoryInfo
            If IO.Directory.Exists(FolderBrowserDialog1.SelectedPath & "\C++ Projects") Then
                desFolder = New DirectoryInfo(FolderBrowserDialog1.SelectedPath & "\C++ Projects")
            Else
                'Create the same name folder under the choosed destination folder  
                desFolder = Directory.CreateDirectory(FolderBrowserDialog1.SelectedPath & "\C++ Projects")
            End If

            Dim var_s1max As Integer = sourceFolder1.GetFiles("*", SearchOption.AllDirectories).Length
            Dim var_s2max As Integer = sourceFolder2.GetFiles("*", SearchOption.AllDirectories).Length

            ProgressBar1.Maximum = var_s1max + var_s2max

            'Copy each file  
            For Each file1 As FileInfo In sourceFolder1.GetFiles("*", SearchOption.AllDirectories)
                Dim desfolder1 As DirectoryInfo

                desfolder1 = Directory.CreateDirectory(FolderBrowserDialog1.SelectedPath & "\C++ Projects\123")

                IO.File.Copy(file1.FullName, desfolder1.FullName & "\ & File1.Name, True)
                'Display progress on ProgressBar1
                ProgressBar1.Value += 1
                'Display log on Label1  
                'Label1.Text = ProgressBar1.Value & " files has been completed!" & vbCrLf & file.Name & " is being copied."
                Application.DoEvents()
            Next

            For Each file2 As FileInfo In sourceFolder2.GetFiles("*", SearchOption.AllDirectories)
                Dim desfolder2 As DirectoryInfo

                desfolder2 = Directory.CreateDirectory(FolderBrowserDialog1.SelectedPath & "\C++ Projects\Video")

                IO.File.Copy(file2.FullName, desfolder2.FullName & "\ & file2.Name, True)
                'Display progress on ProgressBar1
                ProgressBar1.Value += 1
                'Display log on Label1  
                'Label1.Text = ProgressBar1.Value & " files has been completed!" & vbCrLf & file.Name & " is being copied."
                Application.DoEvents()
            Next

        End If

    End Sub

End Class

Thank You !!


Saturday, September 26, 2015 12:34 PM | 1 vote

One thing you can do is quit using the code "Application.DoEvents()" which is unecessary*.* I'm not certain why it is ever used*.*

The meaning from Microsoft for it is "If you call DoEvents in your code, your application can handle the other events. For example, if you have a form that adds data to a ListBox and add DoEvents to your code, your form repaints when another window is dragged over it. If you remove DoEvents from your code, your form will not repaint until the click event handler of the button is finished executing."

More than likely whatever code is delaying a Form from redrawing should probably be run within a thread in order not to interefere with the main UI. Regardless that particular line of code is pretty much never used by anybody because it doesn't really do anything. And even if the Form redraws the UI will be frozen by some synchronous operation which means the code running should be run from a location where it will not interfere with the main UI's operation.

Update: The below code requires a Form with a Button, ProgressBar and BackgroundWorker from the ToolBox.

Option Strict On

Imports System.IO

Public Class Form1

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.CenterToScreen()
        ProgressBar1.Minimum = 0
        BackgroundWorker1.WorkerReportsProgress = True
        BackgroundWorker1.WorkerSupportsCancellation = True
    End Sub

    Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
        Try
            BackgroundWorker1.CancelAsync()
        Catch ex As Exception
        End Try
    End Sub

    Dim FBD1Path As String = ""
    Dim FBD2Path As String = ""
    Dim TotalBytes As Integer = 0
    Dim ReadBytes As Integer = 0

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        ProgressBar1.Value = 0
        Using FBD1 As New FolderBrowserDialog
            FBD1.Description = "Source Folder"
            FBD1.SelectedPath = "C:\Users\John\Desktop"
            FBD1.ShowNewFolderButton = False
            If FBD1.ShowDialog = Windows.Forms.DialogResult.OK Then
                FBD1Path = FBD1.SelectedPath
                Using FBD2 As New FolderBrowserDialog
                    FBD2.Description = "Destination Folder"
                    FBD2.SelectedPath = "C:\Users\John\Desktop"
                    FBD2.ShowNewFolderButton = True
                    If FBD2.ShowDialog = Windows.Forms.DialogResult.OK Then
                        FBD2Path = FBD2.SelectedPath
                        TotalBytes = 0
                        ReadBytes = 0
                        Button1.Enabled = False
                        BackgroundWorker1.RunWorkerAsync()
                    End If
                End Using
            End If
        End Using
    End Sub

    Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        For Each Item In My.Computer.FileSystem.GetFiles(FBD1Path)
            TotalBytes += CInt(My.Computer.FileSystem.GetFileInfo(Item).Length)
        Next
        BackgroundWorker1.ReportProgress(1)
        For Each Item In My.Computer.FileSystem.GetFiles(FBD1Path)
            Using SourceFile As FileStream = File.Open(Item, FileMode.Open, FileAccess.Read)
                Using DestFile As FileStream = File.Open(FBD2Path & Item.Substring(Item.LastIndexOf("\"c), Item.Count - Item.LastIndexOf("\"c)), FileMode.OpenOrCreate)
                    Dim SFLength As Integer = CInt(SourceFile.Length)
                    Dim InfoToCopy(4096) As Byte
                    While CInt(DestFile.Length) < SFLength
                        ReadBytes = SourceFile.Read(InfoToCopy, 0, 4096)
                        DestFile.Write(InfoToCopy, 0, ReadBytes)
                        BackgroundWorker1.ReportProgress(2)
                    End While
                End Using
            End Using
        Next
    End Sub

    Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
        If e.ProgressPercentage = 1 Then ProgressBar1.Maximum = TotalBytes
        If e.ProgressPercentage = 2 Then ProgressBar1.Value += ReadBytes
    End Sub

    Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
        Button1.Enabled = True
    End Sub

End Class

La vida loca


Saturday, September 26, 2015 2:08 PM | 1 vote

Hi,

I need to copy a directory from one place to another. So I have used the following code to do that.

My.Computer.FileSystem.CopyDirectory(var_originfilepath, var_copypath, True)

So this time I need to activate a progress bar when this directory is copying.

There are several ways you can do this, depending on what you want.

For example, if you create a class which has everything needed (which would include a BackgroundWorker) then instead of copying, it creates a new directory path and copies each file to that new directory path.

That's pretty easy, so here's where it [may] get difficult: If you want to have true progress reporting - that is, per file copied you see it update per byte copied - then it can be done but it gets involved.

If, instead, you can live with just showing the progress per file copied (once it has been copied), that's much easier and a lot less code.

I can show you what I mean if you're interested.

I'm using .net framework 2.0.

I haven't read this entire thread so you may have answered this, but why are you using 2.0? If you're using VS2008, you can access framework 3.5 which is head and shoulders better than the older 2.0..

"I never failed once... It just happened to be a 2000-step process." -- Thomas Edison


Saturday, September 26, 2015 3:28 PM

Hi Frank !!

As you said I can use .net framework 3.5 with VS2008. I think there is no way to do my job with .net framework 2.0. I have tried the above code that Mr. Monkeyboy replied to me. But it's not the solution for me yet. The reason is that code doesn't works with folders whether there are sub folders. So can you show me another way to do my job with following code and background worker.

My.Computer.FileSystem.CopyDirectory(var_originfilepath, var_copypath, True)

Thanks in Advance !!


Saturday, September 26, 2015 3:30 PM

Well this is weird ... several of the posts aren't showing.

Let's see if I post this maybe they'll show up again.

"I never failed once... It just happened to be a 2000-step process." -- Thomas Edison


Saturday, September 26, 2015 3:32 PM | 1 vote

Hi Frank !!

As you said I can use .net framework 3.5 with VS2008. I think there is no way to do my job with .net framework 2.0. I have tried the above code that Mr. Monkeyboy replied to me. But it's not the solution for me yet. The reason is that code doesn't works with folders whether there are sub folders. So can you show me another way to do my job with following code and background worker.

My.Computer.FileSystem.CopyDirectory(var_originfilepath, var_copypath, True)

Thanks in Advance !!

There it is.

*****

I'll work on it a while and post back something tomorrow. I'll also upload the project folder for you to use once I'm done.

It won't be as complete as it could be, but I'll get the ball rolling anyway.

"I never failed once... It just happened to be a 2000-step process." -- Thomas Edison


Saturday, September 26, 2015 5:29 PM | 1 vote

Hi Frank !!

As you said I can use .net framework 3.5 with VS2008. I think there is no way to do my job with .net framework 2.0. I have tried the above code that Mr. Monkeyboy replied to me. But it's not the solution for me yet. The reason is that code doesn't works with folders whether there are sub folders. So can you show me another way to do my job with following code and background worker.

My.Computer.FileSystem.CopyDirectory(var_originfilepath, var_copypath, True)

Thanks in Advance !!

I didn't alter the code to provide additional subfolder searching, creating anew in the folder to copy to, etc, which could be performed simply but I've not the time for performing that.

La vida loca


Sunday, September 27, 2015 5:02 AM | 1 vote

Hi,

I need to copy a directory from one place to another. So I have used the following code to do that.

My directory capacity is less than 10MB. 

I didn't notice the capacity issue of less than 10 MB.

I altered the original code I displayed so that it would recreate the source folder and any subfolders within the source folder to the destination location prior to writing files from the source folder and any subfolders to the destination locations created folders and subfolders.

I tested the code on various folders including one with 78 sub folders, 6,775 files, 35,262,045 bytes total and no issues occured. Also tested copying to a memory stick (thumb drive) that was empty and no issues occured.

The code was also altered to write each file at one time rather than writing blocks from each file until all blocks were written which cause the code to run faster.

Also the progress bar min and max are now 0 and 100. The reason for that is that the total bytes of all files could be a Long rather than Integer. The progress bars value only works with integer. Also files byte counts are in Long returned by "My.Computer.FileSystem.GetFileInfo(FilesPathandName).Length" although that would be much larger than 10 MB to return a Long for one file and integer type handles up to 2,147,483,647.

Since you have a 10 MB limit then in the code below there would need to be an If statement provided after the For/Next for TotalBytes. However there's a difference between disk space for a file and total bytes of a file. Depending on the disk format depends on how many sectors will be allocated to contain a files bytes. And the last sector allocated may only contain a couple of bytes. So if a file was 4097 bytes in size and sectors were such that the disk format provides 4096 bytes for a sector then two sectors would be used to store a 4097 byte file so 4096 * 2 disk space (8192 bytes) would be used for storing the file of 4097 bytes.

If TotalBytes < some amount you specify Then

 ' All the code that runs after the For/Next for TotalBytes would go here prior to End Sub

End If

Or you can add code to find what the source folders total size on disk is to see if it can be copied. That information is different than the source folders size if you look at the properties of a source folder by right clicking on it and viewing its properties.

Option Strict On

Imports System.IO

Public Class Form1

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.Location = New Point(CInt((Screen.PrimaryScreen.WorkingArea.Width / 2) - (Me.Width / 2)), CInt((Screen.PrimaryScreen.WorkingArea.Height / 2) - (Me.Height / 2)))
        ProgressBar1.Minimum = 0
        ProgressBar1.Maximum = 100
        BackgroundWorker1.WorkerReportsProgress = True
        BackgroundWorker1.WorkerSupportsCancellation = True
    End Sub

    Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
        Try
            BackgroundWorker1.CancelAsync()
        Catch ex As Exception
        End Try
    End Sub

    Dim FBD1Path As String = ""
    Dim FBD2Path As String = ""
    Dim TotalBytes As Long = 0
    Dim ReadBytes As Long = 0

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        ProgressBar1.Value = 0
        Using FBD1 As New FolderBrowserDialog
            FBD1.Description = "Source Folder"
            FBD1.SelectedPath = "C:\Users\John\Desktop"
            FBD1.ShowNewFolderButton = False
            If FBD1.ShowDialog = Windows.Forms.DialogResult.OK Then
                FBD1Path = FBD1.SelectedPath
                Using FBD2 As New FolderBrowserDialog
                    FBD2.Description = "Destination Folder"
                    FBD2.SelectedPath = "C:\Users\John\Desktop"
                    FBD2.ShowNewFolderButton = True
                    If FBD2.ShowDialog = Windows.Forms.DialogResult.OK Then
                        FBD2Path = FBD2.SelectedPath
                        TotalBytes = 0
                        ReadBytes = 0
                        Button1.Enabled = False
                        Button1.BackColor = Color.OrangeRed
                        BackgroundWorker1.RunWorkerAsync()
                    End If
                End Using
            End If
        End Using
    End Sub

    Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        Dim FileList As New List(Of String)
        Dim FolderSelected As String = FBD1Path.Split("\"c)(FBD1Path.Split("\"c).Count - 1)
        FileList = IO.Directory.GetFiles(FBD1Path, "*", SearchOption.AllDirectories).ToList
        For Each Item In FileList
            Dim Temp As String = IO.Path.GetDirectoryName(Item).Substring(IO.Path.GetDirectoryName(Item).IndexOf(FolderSelected), IO.Path.GetDirectoryName(Item).Count - IO.Path.GetDirectoryName(Item).IndexOf(FolderSelected))
            If Directory.Exists(FBD2Path & "\" & Temp) = False Then
                Directory.CreateDirectory(FBD2Path & "\" & Temp)
            End If
        Next
        For Each Item In FileList
            TotalBytes += My.Computer.FileSystem.GetFileInfo(Item).Length
        Next
        For Each Item In FileList
            Using SourceFile As FileStream = File.Open(Item, FileMode.Open, FileAccess.Read)
                Dim Temp As String = FBD2Path & "\" & IO.Path.GetDirectoryName(Item).Substring(IO.Path.GetDirectoryName(Item).IndexOf(FolderSelected), IO.Path.GetDirectoryName(Item).Count - IO.Path.GetDirectoryName(Item).IndexOf(FolderSelected))
                Temp &= "\" & IO.Path.GetFileName(Item)
                Using DestFile As FileStream = File.Open(Temp, FileMode.OpenOrCreate)
                    Dim SFLength As Integer = CInt(SourceFile.Length)
                    Dim ActualBytesRead As Integer = 0
                    Dim InfoToCopy(SFLength - 1) As Byte ' Sizes byte array to SFLength. 1 dimensional Arrays are always 1 larger than size they are set to which is why - 1 is used.
                    ActualBytesRead = SourceFile.Read(InfoToCopy, 0, SFLength)
                    ReadBytes += ActualBytesRead
                    DestFile.Write(InfoToCopy, 0, ActualBytesRead)
                    BackgroundWorker1.ReportProgress(1)
                End Using
            End Using
        Next
    End Sub

    Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
        If e.ProgressPercentage = 1 Then ProgressBar1.Value = CInt((100 / TotalBytes) * ReadBytes)
    End Sub

    Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
        Button1.Enabled = True
        Button1.BackColor = SystemColors.Control
    End Sub

End Class

La vida loca


Sunday, September 27, 2015 6:24 AM | 1 vote

With this code you could get the actual space required for a files size on disk for the volume you want to copy the files to. Which would require some alteration to the last code I posted. The below code would have to be added to it and altered for determing for the location for the files to be copied to how much disk space would be required for each file. And all that added together to determine if the size was greater than 10 MB.

Option Strict On

Imports System.Management ' Add ref Assemblies, Framework, System.Management
Imports System.IO

Public Class Form1

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.Location = New Point(CInt((Screen.PrimaryScreen.WorkingArea.Width / 2) - (Me.Width / 2)), CInt((Screen.PrimaryScreen.WorkingArea.Height / 2) - (Me.Height / 2)))
        Label1.Text = "Waiting"
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        ListBox1.Items.Clear()
        Label1.Text = "Waiting"
        Label1.Refresh()
        If File.Exists("C:\Users\John\Desktop\Text Files\Simple Test Text.txt") Then

            Dim ByteLength As Long = FileLen("C:\Users\John\Desktop\Text Files\Simple Test Text.txt") ' Get file length
            Dim ClusterSize As Long = 0
            Dim ClusterSpaceUsed As Double = 0
            Dim ClustersUsed As Long = 0
            Dim SpaceUsed As Long = 0

            Dim searcher As New ManagementObjectSearcher("root\CIMV2", "SELECT * FROM Win32_Volume")

            For Each queryObj As ManagementObject In searcher.Get() ' Get block size, allocation unit size, cluster size of disk.
                Dim Temp As String = queryObj("Caption").ToString
                If Temp.Contains("C:\") Then
                    Label1.Text = "Volume " & Temp.ToString
                    ClusterSize = CLng(queryObj("BlockSize"))
                    Label1.Text &= " cluster size is " & ClusterSize.ToString & " bytes per cluster." & vbCrLf
                    ListBox1.Items.Add(Temp & "  " & ClusterSize.ToString)
                    ClusterSpaceUsed = ByteLength / ClusterSize

                    ClustersUsed = CLng(Math.Ceiling(ClusterSpaceUsed))

                    SpaceUsed = ClustersUsed * ClusterSize

                    Label1.Text &= "The file " & ChrW(34) & "C:\Users\John\Desktop\Text Files\Simple Test Text.txt" & ChrW(34) & " size on disk is " & vbCrLf & _
                                            "(Clusters used = Files Byte Length / Cluster Size = " & ClusterSpaceUsed.ToString & " then total clusters used = " & vbCrLf & _
                                             ClustersUsed.ToString & " then total space used on disk " & ChrW(61) & " clusters used * cluster size which comes out to) " & _
                                            SpaceUsed.ToString & " bytes." & vbCrLf & _
                                            "The actual files size is " & ByteLength.ToString & " bytes."
                Else
                    ClusterSize = CLng(queryObj("BlockSize"))
                    ListBox1.Items.Add(Temp & "  " & ClusterSize.ToString)
                End If
            Next
        End If
    End Sub

End Class

La vida loca


Sunday, September 27, 2015 10:57 AM

Hii Frank L.Smith,

First of all I would to thank you for give me the solution. You have had a hard work and always I appreciate it very much and more. Now any one can use these codes and files to copy directories in their own way. So I think this is the best answer for me and also I marked this as the correct answer also. Can you do a little thing for me again? I like to change "Megs" and "Gigs" words to "MB" and "GB" like my attachment. Also i tried to change in your class file but there is some errors for me. However I appreciate  your hard work again and again. This is the perfect solution for me and I have joined these codes with my project successfully.

Thanks in Advance !!!


Sunday, September 27, 2015 11:01 AM

Hello Mr.Monkeyboy

I like to thank you who giving me solutions for my problems and questions also. Actually I didn't try these codes yet, but maybe this will be a another answer for my question. So I appreciate your works for me.

Thanks in Advance !!


Sunday, September 27, 2015 1:44 PM | 1 vote

Hii Frank L.Smith,

First of all I would to thank you for give me the solution. You have had a hard work and always I appreciate it very much and more. Now any one can use these codes and files to copy directories in their own way. So I think this is the best answer for me and also I marked this as the correct answer also. Can you do a little thing for me again? I like to change "Megs" and "Gigs" words to "MB" and "GB" like my attachment. Also i tried to change in your class file but there is some errors for me. However I appreciate  your hard work again and again. This is the perfect solution for me and I have joined these codes with my project successfully.

Thanks in Advance !!!

I'm glad it helped. :)

*****

This is the revised version:

http://www.fls-online.com/VBNet_Forum/09-27-15/SimpleFileAndDirectoryCopy.zip

This one has the class library as a part of the same assembly, so if you make a change to the code there, it shouldn't give you a problem when you compile it. I've already changed what you show above though (but check it and modify it if I missed part of it).

"I never failed once... It just happened to be a 2000-step process." -- Thomas Edison


Sunday, September 27, 2015 3:01 PM

Hii FLS,

Still there is same mistake that I have told you. I don't know the reason. Please refer the attachment. May be you can find the reason for it.

Thank You !!


Sunday, September 27, 2015 3:10 PM

Hii FLS,

Still there is same mistake that I have told you. I don't know the reason. Please refer the attachment. May be you can find the reason for it.

Thank You !!

Right, the older version doesn't support that. I had to change a number of things for this.

If you'll look only at what's new today (in the VS2008 subfolder), you'll see that the class library is now a part of it:

In this "version" of it, what you show above has been replaced with the following:

Dim instructions As New BGW_Instructions
Dim diList As New List(Of DirectoryInfo)
diList.Add(sourceDI)

With instructions
    .SourceDirectoryInfoList = diList
    .TargetBaseDirectory = targetDI
    .ParsingType = parsingInstructions
End With

tmr = New System.Windows.Forms.Timer() With _
                              {.Interval = 500, _
                               .Enabled = True}

_operationSW = New Stopwatch

bgw = New System.ComponentModel.BackgroundWorker() With _
                             {.WorkerSupportsCancellation = True}

bgw.RunWorkerAsync(instructions)

In fact, you can throw that stuff away from yesterday. I started to do that before I zipped it up but forgot to.

"I never failed once... It just happened to be a 2000-step process." -- Thomas Edison


Sunday, September 27, 2015 3:41 PM

Hi Frank,

Actually now It's fine. 100% successfully. However I appreciate your hard works for me again.

Thank You !


Sunday, September 27, 2015 3:44 PM | 1 vote

Hi Frank,

Actually now It's fine. 100% successfully. However I appreciate your hard works for me again.

Thank You !

You're welcome. :)

I was just about to post this, so I will anyway:

http://www.fls-online.com/VBNet_Forum/09-27-15/SimpleFileAndDirectoryCopy2.zip

That one doesn't have any of the VS2010 stuff in it.

"I never failed once... It just happened to be a 2000-step process." -- Thomas Edison


Sunday, September 27, 2015 7:41 PM | 1 vote

Hi Frank

Hope life is treating you well

Great to see the FileAndDirectoryCopy class you created is still proving useful/popular!

Darren Rose


Sunday, September 27, 2015 8:15 PM

Hi Frank

Hope life is treating you well

Great to see the FileAndDirectoryCopy class you created is still proving useful/popular!

Darren Rose

:)

Actually this is a watered-down version of that one.

"I never failed once... It just happened to be a 2000-step process." -- Thomas Edison


Monday, September 28, 2015 7:55 AM

Hello Frank,

Is there are any way to contact you? Like an E-mail address.

Thank You!!


Monday, September 28, 2015 1:32 PM

Hello Frank,

Is there are any way to contact you? Like an E-mail address.

Thank You!!

I'd prefer to converse here (although it might be better in another thread).

Are you having problems with the code?

"I never failed once... It just happened to be a 2000-step process." -- Thomas Edison