Kopiowanie całych folderów z Progressbarem jest nieco trudniejsze niż kopiowanie tylko jednego pliku. Aby użyć File stream’a do kopiowania plików należy zbadać folder w celu ich odnalezienia i określić ile sub folderów znajduje się wewnątrz folderu, następnie zbadać znalezione subfoldery w poszukiwaniu plików i kolejnych subfolderów, trzeba również zachować hierarchie folderów i plików. Stworzyłem algorytm który spełnia te kryteria. Jego opis publikuje poniżej:
Najpierw ułuż elementy tak jak na obrazku poniżej
Następnir dodajemy BackgroundWorker i FolderBrowser x2 do naszej formy
Jeśli wszystko poszło dobrze zobaczymy je w polu pod formą
Zmieniamy tekst poszczególnych elementów tak jak na obrazku
Public Class Form1
Dim directoryTargetLocation As String 'Selected file path
Dim Destinydirectory As String 'Selected dest directory path
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
FolderBrowserDialog1.Description = "Select directory"
With FolderBrowserDialog1
If .ShowDialog() = DialogResult.OK Then
directoryTargetLocation = .SelectedPath
Label1.Text = directoryTargetLocation.ToString
End If
End With
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
FolderBrowserDialog2.Description = "Select destiny directory"
With FolderBrowserDialog2
If .ShowDialog() = DialogResult.OK Then
Destinydirectory = .SelectedPath
Label2.Text = Destinydirectory.ToString
End If
End With
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim parts As String() = directoryTargetLocation.Split(New Char() {"\"c})
Dim filename As String = parts(parts.Count - 1) 'target folder name
Dim dir_path As String = "" 'directory without target folder name
For f As Integer = 0 To parts.Count - 2
dir_path += parts(f) + "\"
Next
Dim copied As Integer = 0
Dim counter As Integer = IO.Directory.GetFiles(directoryTargetLocation, "*.*", IO.SearchOption.AllDirectories).Length 'counts the number of files
SetProgressbar(counter, ProgressBar2) 'Sets ProgressBar maximum to number of files
setLabelTxt("Copied (0/" + counter.ToString + ")", Label4) 'displays the amount of copied files
Dim FolderList As New List(Of String)
FolderList.Add(directoryTargetLocation) 'Set first folder
Do While True
If (BackgroundWorker1.CancellationPending = True) Then 'cancel loop
e.Cancel = True
Exit Do
End If
Dim FoldersInsideDirectory As New List(Of String)
If FolderList.Count = 0 Then
Exit Do 'If there is no folder to copy Exit Do
Else
For l As Integer = 0 To FolderList.Count - 1
If (BackgroundWorker1.CancellationPending = True) Then 'stop for loop
e.Cancel = True
Exit For
End If
Dim sourceDirectoryInfo As New System.IO.DirectoryInfo(FolderList(l))
Dim dest As String = FolderList(l).Replace(dir_path, "")
If (Not System.IO.Directory.Exists(Destinydirectory + "\" + dest)) Then 'create subFolder inside directory
System.IO.Directory.CreateDirectory(Destinydirectory + "\" + dest)
End If
Dim fileSystemInfo As System.IO.FileSystemInfo
For Each fileSystemInfo In sourceDirectoryInfo.GetFileSystemInfos
If (BackgroundWorker1.CancellationPending = True) Then
e.Cancel = True
Exit For
End If
Dim destinationFileName As String = System.IO.Path.Combine(Destinydirectory + "\" + dest, fileSystemInfo.Name)
If TypeOf fileSystemInfo Is System.IO.FileInfo Then
Dim streamRead As New System.IO.FileStream(fileSystemInfo.FullName, System.IO.FileMode.Open)
setLabelTxt(fileSystemInfo.FullName.ToString, Label3)
Dim streamWrite As New System.IO.FileStream(Destinydirectory + "\" + dest + "\" + fileSystemInfo.Name, IO.FileMode.Create, IO.FileAccess.Write, IO.FileShare.None)
Dim lngLen As Long = streamRead.Length - 1
setLabelTxt("Copy bytes : (0/" + (lngLen * 100).ToString + ")", Label5)
Dim byteBuffer(1048576) As Byte 'our stream buffer
Dim intBytesRead As Integer 'number of bytes read
While streamRead.Position < lngLen 'keep streaming until EOF
If (BackgroundWorker1.CancellationPending = True) Then
e.Cancel = True
Exit While
End If
BackgroundWorker1.ReportProgress(CInt(streamRead.Position / lngLen * 100))
setLabelTxt("Copy bytes : (" + CInt(streamRead.Position).ToString + "/" + (lngLen * 100).ToString + ")", Label5)
intBytesRead = (streamRead.Read(byteBuffer, 0, 1048576))
streamWrite.Write(byteBuffer, 0, intBytesRead)
End While
'Clean up
streamWrite.Flush()
streamWrite.Close()
streamRead.Close()
addProgress(1, ProgressBar2)
copied += 1
setLabelTxt("Copied (" + copied.ToString + "/" + counter.ToString + ")", Label4)
Else
FoldersInsideDirectory.Add(fileSystemInfo.FullName)
End If
Next
Next
FolderList.Clear()
FolderList = FoldersInsideDirectory
End If
Loop
End Sub
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Button1.Enabled = False 'button1 block
Button2.Enabled = False 'button2 block
Button3.Enabled = False
BackgroundWorker1.RunWorkerAsync() 'do magic
End Sub
Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
ProgressBar1.Value = e.ProgressPercentage
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
If e.Cancelled = True Then
MsgBox("Copy canceled!")
Else
MsgBox("Copy complete!")
End If
Button1.Enabled = True
Button2.Enabled = True
Button3.Enabled = True
End Sub
Private Sub setLabelTxt(ByVal text As String, ByVal lbl As Label)
If lbl.InvokeRequired Then
lbl.Invoke(New setLabelTxtInvoker(AddressOf setLabelTxt), text, lbl)
Else
lbl.Text = text
End If
End Sub
Private Delegate Sub setLabelTxtInvoker(ByVal text As String, ByVal lbl As Label)
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
If BackgroundWorker1.IsBusy Then
BackgroundWorker1.CancelAsync()
End If
End Sub
Private Sub SetProgressbar(ByVal val As Integer, ByVal progressba As ProgressBar)
If progressba.InvokeRequired Then
progressba.Invoke(New SetProgressbarInvoker(AddressOf SetProgressbar), val, progressba)
Else
progressba.Value = 0
progressba.Maximum = val
End If
End Sub
Private Delegate Sub SetProgressbarInvoker(ByVal val As Integer, ByVal progressba As ProgressBar)
Private Sub addProgress(ByVal val As Integer, ByVal progressba As ProgressBar)
If progressba.InvokeRequired Then
progressba.Invoke(New addProgressInvoker(AddressOf addProgress), val, progressba)
Else
progressba.Value += val
End If
End Sub
Private Delegate Sub addProgressInvoker(ByVal val As Integer, ByVal progressba As ProgressBar)
End Class



10 komentarzy
Przejdź do formularza komentarza
Nice work ! It’s possible to converte to move folder instead of copy ?
Autor
Using this loop you can’t do that. Becouse you don’t manipulate main file, you just read and copy file by byte. FIlestream can’t delete main file. You can add comand „System.IO.File.Delete( FileToDelete )” to the loop, when file has been copied then it will delete it.
how to copy hidden files with this?
thanks.
Autor
you can check the file attribute using:
If Not fileSystemInfo.Attributes = Nothing AndAlso fileSystemInfo.Attributes = System.IO.FileAttributes.Hidden Then …
or check directory attribute using the same loop.
Nice Job!!
How to select multiple folders?
Thanks
Autor
Hello,
I do not quite understand what you want to do
Try to list all directories using:
For Each Dir As String In Directory.GetDirectories(„your directory”)
” Copy metod
Next
and call copy method for each folders
Fantastic Work, Impressive
Please tell me how do I copy only selected file formats from the source folder to destination folders using your above code, Sometimes 2 destination folders
Ex:
Source Folder have *.dat, *.abq, *.zas, *.slp, *.log, *.zipp, *.mat and *.mno files,
I want to copy only *.abq, *.dat, *.log, and *.mno files to Destination folder ( Sometimes 2 destination folders)
Thank You
Autor
Hi,
Thank you for the comment 😀
first you need to define an Array, this will help you easyli manage all extensions:
Dim extensions As String() = {„.abq”, „.dat”, „.log”}
then put a logic below the line 83
83: If TypeOf fileSystemInfo Is System.IO.FileInfo Then
84: If extensions.Contains(fileSystemInfo.Extension) Then
85: …..
That should do the work 😉
But remember to change the file count logic to set the progressbar properly
HI Sir,
I just started learning programing and your code helps me a lot. I was only wondering how to add estimated remaining time and transfer rate of the copying files.
Thank you in advance
Hi Admin,
Thank you, this is awesome. I have customised this after going through the code. However there is one thing which stands out for me, yes this copys every folder (directory) perfectly, but It doesn’t copy Documents (My Documents) directory, yes it copys individual folder within it, but it does copy all of the folder (Directory). With out folders (Directory) no problem. Why not all of Documents (My Documents).
Thank you inadvance Baz