Search code examples
vb.netbackgroundworker

Backgroundworker not starting copy


I am a novice at VB.NET and am working on an app the read the contents of a text file and use the paths therein for a file/folder copy. I am running the copy through a backgroundworker which does not seem to take the line string. To troubleshoot I have placed a MessageBox.Show(line) under the line reading logic to see if it is reading the path. It is not and jumps straight to my BackgroundWorker1_RunWorkerCompleted sub.

Can anyone see where I am going wrong?!

Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As ComponentModel.DoWorkEventArgs, Optional ByVal Overwrite As Boolean = True) Handles BackgroundWorker1.DoWork

    Dim deststring As String

    ' Open config.txt with the Using statement.
    Using r As StreamReader = New StreamReader(Application.StartupPath + "\CONFIG.txt")

        Dim line As String

        ' Read first line.
        line = r.ReadLine

        ' Loop over each line in file, While list is Not Nothing.
        Do While (Not line Is Nothing)

            ' Read line and filter based on logic
            If line.StartsWith("*") Then
                r.ReadLine()
            ElseIf line.Contains(Destpath) Then
                r.ReadLine()
            ElseIf line.Equals("%USERPROFILE%\Desktop") Then
                line = desktoppath
            ElseIf line.Equals("%USERPROFILE%\Downloads") Then
                line = downloadsPath
            ElseIf line.Equals("%USERPROFILE%\Contacts") Then
                line = contactspath
            ElseIf line.Equals("%USERPROFILE%\Documents") Then
                line = documentspath
            ElseIf line.Equals("%USERPROFILE%\Favorites") Then
                line = favoritespath
            ElseIf line.Equals("%USERPROFILE%\Links") Then
                line = linkspath
            ElseIf line.Equals("%USERPROFILE%\Music") Then
                line = Musicpath
            ElseIf line.Equals("%USERPROFILE%\Pictures") Then
                line = picturespath
            ElseIf line.Equals("%USERPROFILE%\SavedGames") Then
                line = savedgamespath
            ElseIf line.Equals("%USERPROFILE%\SavedSearches") Then
                line = savedsearchespath
            ElseIf line.Equals("%USERPROFILE%\Videos") Then
                line = videospath
            ElseIf line.Contains("%USERNAME%") Then
                line = line.Replace("%USERNAME%", Username)
            Else

                Console.Writeline(line)

                'Read line and create a full path for the destination
                Dim SubPath As String = line.Split("\").Last
                Dim FullDestPath As String = Destpath & "\" & SubPath

                Console.Writeline(FullDestPath)

                If Not System.IO.Directory.Exists(FullDestPath) Then
                    System.IO.Directory.CreateDirectory(FullDestPath)
                End If


                'Get directory info's
                Dim SourceDir As DirectoryInfo = New DirectoryInfo(line)
                Dim DestDir As DirectoryInfo = New DirectoryInfo(FullDestPath)
                Dim ChildFile As FileInfo

                'Loop through each file in the SourceDir
                For Each ChildFile In SourceDir.GetFiles()

                    'Display file being copied
                    SetLabelText_ThreadSafe(Me.lblStatus, "Copying: " & line & "\" & ChildFile.Name & "")

                    'Do the copy
                    ChildFile.CopyTo(Path.Combine(DestDir.FullName, ChildFile.Name), True)

                    deststring = DestDir.ToString & "\" & ChildFile.Name
                    Dim sourcedirstring As String
                    sourcedirstring = SourceDir.ToString & "\" & ChildFile.Name

                    'Open Stream
                    Dim CopyStream As New FileStream(sourcedirstring, FileMode.Open, FileAccess.Read)
                    Dim NewStream As New FileStream(deststring, FileMode.CreateNew)
                    Dim Buffer(100000) As Byte
                    Dim BytesRead As Integer

                    'Try loop for each file
                    Try
                        Do
                            BytesRead = CopyStream.Read(Buffer, 0, Buffer.Length)
                            NewStream.Write(Buffer, 0, BytesRead)
                            PercentComplete = (NewStream.Length / CopyStream.Length * 100)
                            PercentComplete = Decimal.Round((PercentComplete), 2)
                            If PercentComplete > 100 Then
                                PercentComplete = "0"
                            End If

                            'if the file count is only 1 file then make both progress bars the same so that the current file and total are the same
                            If filecount = 1 Then
                                percentage = ((NewStream.Length + filetotalsofarcopied) / Overallsize.ToString * 100)
                                percentage = Decimal.Round((percentage), 2)
                                If percentage > 100 Then
                                    percentage = 0
                                End If
                                SetLabelText_ThreadSafe(Me.lblTotalProgress, "" & percentage & "%")
                            Else
                                Timer6.Start()
                                percentage2 = ((NewStream.Length + filetotalsofarcopied) / Overallsize.ToString * 100)
                                percentage2 = Decimal.Round((percentage2), 2)
                                If percentage2 > 100 Then
                                    percentage2 = 0
                                End If
                                SetLabelText_ThreadSafe(Me.lblTotalProgress, "" & percentage2 & "%")
                            End If

                            SetLabelText_ThreadSafe(Me.lblCurrentFileProgress, "" & PercentComplete & "%")

                            Dim time As Long = Label22.Text

                            'Calculate copy speed
                            Dim kbps As Double = (NewStream.Length + filetotalsofarcopied) / (time * 1024)
                            If kbps < 1024 Then
                                SetLabelText_ThreadSafe(Me.lblCopy, String.Format("Copy Speed: {0:0.00} KB/s", kbps))
                            Else
                                SetLabelText_ThreadSafe(Me.lblCopy, String.Format("Copy Speed: {0:0.00} MB/s", kbps / 1024))
                            End If

                        Loop Until BytesRead = 0 And PercentComplete = 100

                    Catch ex As Exception
                    Finally
                        CopyStream.Dispose()
                        NewStream.Dispose()
                    End Try

                    'File counter
                    int3 = int3 + 1

                    'Calculate data being moved for eta to completion
                    Dim filetotalbytes As Double = ChildFile.Length
                    filetotalsofarcopied = filetotalbytes + filetotalsofarcopied

                    'Check for pending cancel
                    If BackgroundWorker1.CancellationPending = True Then
                        BackgroundWorker1.CancelAsync()
                        Exit Sub
                    End If

                Next

                'Loop through Sub directories of SourceDir
                Dim SubDir As DirectoryInfo
                For Each SubDir In SourceDir.GetDirectories()
                    CopyDirectory(SubDir.FullName, Path.Combine(DestDir.FullName, SubDir.Name), Overwrite)
                Next
            End If

            ' Read in the next line.
            line = r.ReadLine

        Loop

    End Using

End Sub

UPDATE: Included .text file contents:

***DESTINATION***
D:\Test
***Sources***
%USERPROFILE%\Downloads
%USERPROFILE%\Favorites
D:\User Data\Adam\Documents\Test

Solution

  • You should remove the calls to ReadLine inside the first two Ifs and replace them with the Continue Do keyword.

    In general it is better to have just one call to ReadLine in your code.
    For example you could check for End of Stream using the StreamReader.Peek method.

    Finally the If block should be closed after the %USERNAME% check

        ' removed
        ' line = r.ReadLine()
    
        Dim line As String
        Do While r.Peek <> -1
            line = r.ReadLine()
            Console.Writeline(line)
    
            If line.StartsWith("*") Then
                ' Not significant, skip to the next line
                Continue Do
            ElseIf line.Contains(Destpath) Then
                ' Not significant, skip to the next line
                Continue Do
            ElseIf line.Equals("%USERPROFILE%\Desktop") Then
                line = desktoppath
            ElseIf line.Equals("%USERPROFILE%\Downloads") Then
                line = downloadsPath
            ElseIf line.Equals("%USERPROFILE%\Contacts") Then
                line = contactspath
            ElseIf line.Equals("%USERPROFILE%\Documents") Then
                line = documentspath
            ElseIf line.Equals("%USERPROFILE%\Favorites") Then
                line = favoritespath
            ElseIf line.Equals("%USERPROFILE%\Links") Then
                line = linkspath
            ElseIf line.Equals("%USERPROFILE%\Music") Then
                line = Musicpath
            ElseIf line.Equals("%USERPROFILE%\Pictures") Then
                line = picturespath
            ElseIf line.Equals("%USERPROFILE%\SavedGames") Then
                line = savedgamespath
            ElseIf line.Equals("%USERPROFILE%\SavedSearches") Then
                line = savedsearchespath
            ElseIf line.Equals("%USERPROFILE%\Videos") Then
                line = videospath
            ElseIf line.Contains("%USERNAME%") Then
                line = line.Replace("%USERNAME%", Username)            
            End If
    
            ' Now your line variable should be always correct and            
            ' you can execute your copying logic 
            ......
    
            line = r.ReadLine
        Loop