Solved

VB.NET system.io.file.copy Progress bar.

Posted on 2004-08-06
18
20,440 Views
Last Modified: 2009-05-19
i am building a program that will be copying some large files from across a network. I am trying to show a progress bar for the file being copied
can anyone tell me how to update the progress bar to reflect the status of the copy process.

I am using system.io.file.copy
0
Comment
Question by:Vartana
18 Comments
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 11740023
for 1 file ? you would have to copy it over yourself as opposed to calling File.Copy ....

for multiple files heres a quick example....

Imports System.IO
Imports System.Threading
Public Class Form1
    Inherits System.Windows.Forms.Form
#Region " Windows Form Designer generated code "
    Public Sub New()
        MyBase.New()
        'This call is required by the Windows Form Designer.
        InitializeComponent()
        'Add any initialization after the InitializeComponent() call
    End Sub
    'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub
    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer
    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    Friend WithEvents Label1 As System.Windows.Forms.Label
    Friend WithEvents TextBox1 As System.Windows.Forms.TextBox
    Friend WithEvents Label2 As System.Windows.Forms.Label
    Friend WithEvents TextBox2 As System.Windows.Forms.TextBox
    Friend WithEvents ProgressBar1 As System.Windows.Forms.ProgressBar
    Friend WithEvents Button1 As System.Windows.Forms.Button
    Friend WithEvents RichTextBox1 As System.Windows.Forms.RichTextBox
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.Label1 = New System.Windows.Forms.Label
        Me.TextBox1 = New System.Windows.Forms.TextBox
        Me.Label2 = New System.Windows.Forms.Label
        Me.TextBox2 = New System.Windows.Forms.TextBox
        Me.ProgressBar1 = New System.Windows.Forms.ProgressBar
        Me.Button1 = New System.Windows.Forms.Button
        Me.RichTextBox1 = New System.Windows.Forms.RichTextBox
        Me.SuspendLayout()
        '
        'Label1
        '
        Me.Label1.Location = New System.Drawing.Point(24, 24)
        Me.Label1.Name = "Label1"
        Me.Label1.TabIndex = 0
        Me.Label1.Text = "Source"
        '
        'TextBox1
        '
        Me.TextBox1.Location = New System.Drawing.Point(168, 24)
        Me.TextBox1.Name = "TextBox1"
        Me.TextBox1.TabIndex = 1
        Me.TextBox1.Text = ""
        '
        'Label2
        '
        Me.Label2.Location = New System.Drawing.Point(24, 56)
        Me.Label2.Name = "Label2"
        Me.Label2.TabIndex = 2
        Me.Label2.Text = "Destination"
        '
        'TextBox2
        '
        Me.TextBox2.Location = New System.Drawing.Point(168, 48)
        Me.TextBox2.Name = "TextBox2"
        Me.TextBox2.TabIndex = 3
        Me.TextBox2.Text = ""
        '
        'ProgressBar1
        '
        Me.ProgressBar1.Location = New System.Drawing.Point(8, 240)
        Me.ProgressBar1.Name = "ProgressBar1"
        Me.ProgressBar1.Size = New System.Drawing.Size(272, 23)
        Me.ProgressBar1.Step = 1
        Me.ProgressBar1.TabIndex = 4
        '
        'Button1
        '
        Me.Button1.Location = New System.Drawing.Point(200, 80)
        Me.Button1.Name = "Button1"
        Me.Button1.TabIndex = 5
        Me.Button1.Text = "Go"
        '
        'RichTextBox1
        '
        Me.RichTextBox1.Location = New System.Drawing.Point(16, 112)
        Me.RichTextBox1.Name = "RichTextBox1"
        Me.RichTextBox1.Size = New System.Drawing.Size(264, 120)
        Me.RichTextBox1.TabIndex = 6
        Me.RichTextBox1.Text = ""
        '
        'Form1
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(292, 270)
        Me.Controls.Add(Me.RichTextBox1)
        Me.Controls.Add(Me.Button1)
        Me.Controls.Add(Me.ProgressBar1)
        Me.Controls.Add(Me.TextBox2)
        Me.Controls.Add(Me.Label2)
        Me.Controls.Add(Me.TextBox1)
        Me.Controls.Add(Me.Label1)
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.ResumeLayout(False)
    End Sub
#End Region
    Private Sub updateprogress(ByVal progress As Integer)
        If (progress < Me.ProgressBar1.Maximum AndAlso progress > Me.ProgressBar1.Minimum) Then
            Me.ProgressBar1.Value = progress
        End If
    End Sub
    Private Sub showmessage(ByVal msg As String)
        Me.RichTextBox1.AppendText(msg & vbCrLf)
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim foo As New FileCopy
        AddHandler foo.CopyProgress, AddressOf Me.updateprogress
        AddHandler foo.Message, AddressOf Me.showmessage
        foo.Copy(Me.TextBox1.Text, Me.TextBox2.Text)
    End Sub
End Class
Public Class FileCopy
    Private Class CreateDir
        Public DirectoryName As String
        Public Sub New(ByVal _DirectoryName As String)
            Me.DirectoryName = _DirectoryName
        End Sub
    End Class
    Private Class CopyFile
        Public Source As String
        Public Dest As String
        Public Sub New(ByVal _source As String, ByVal _dest As String)
            Me.Source = _source
            Me.Dest = _dest
        End Sub
    End Class
    Private Directories As ArrayList = New ArrayList 'contains directories to be created
    Private Files As ArrayList = New ArrayList ' contains files to be copied
    Public Event CopyProgress(ByVal progress As Integer)
    Private Sub UpdateProgress(ByVal progress As Integer)
        RaiseEvent CopyProgress(progress)
    End Sub
    Public Event Message(ByVal msg As String)
    Private Sub DoMessage(ByVal msg As String)
        RaiseEvent Message(msg)
    End Sub
    Private Sub CreateDirectories()
        Dim i As Integer
        For i = 0 To Me.Directories.Count - 1
            'create the dir
            Dim dir As CreateDir = DirectCast(Me.Directories(i), CreateDir)
            Me.DoMessage("Creating directory " & dir.DirectoryName)
            Directory.CreateDirectory(dir.DirectoryName)
        Next
    End Sub
    Private Sub CopyFiles()
        Dim i As Integer
        For i = 0 To Me.Files.Count - 1
            Dim cp As CopyFile = DirectCast(Me.Files(i), CopyFile)
            Me.DoMessage("Copying " & cp.Source & " to " & cp.Dest)
            Me.UpdateProgress((CDbl(i + 1) / CDbl(Me.Files.Count)) * 100)
            File.Copy(cp.Source, cp.Dest)
        Next
    End Sub
    Private Sub PrepareInfo(ByVal src As String, ByVal dest As String)
        Try
            Dim tododir As CreateDir = New CreateDir(dest)
            Me.Directories.Add(tododir) 'add it for later
            Dim d As DirectoryInfo = New DirectoryInfo(src)
            Dim f As FileInfo() = d.GetFiles()
            Dim file As FileInfo
            For Each file In d.GetFiles()
                Dim todofile As CopyFile = New CopyFile(file.FullName, dest + "\" + file.Name)
                Me.Files.Add(todofile)
            Next
            Dim folder As DirectoryInfo
            For Each folder In d.GetDirectories() ' take all folders
                PrepareInfo(src + "\" + folder.Name, dest + "\" + folder.Name) 'recursive function calling itself  
            Next
        Catch ex As Exception
            Throw New System.Exception("Unable to copy", ex)
        End Try
    End Sub
    Public Sub Copy(ByVal src As String, ByVal dest As String)
        Try
            '1 get the info
            Me.DoMessage("Building work")
            Me.PrepareInfo(src, dest)
            Me.DoMessage("There are " & Me.Directories.Count & " directories being created")
            Me.DoMessage("There are " & Me.Files.Count & " files being copied")
            '2 actually do the work
            Me.CreateDirectories()
            Me.CopyFiles()
            Me.DoMessage("Complete")
        Catch Ex As Exception
            MessageBox.Show(Ex.ToString())
        End Try
    End Sub
End Class

 
I would further recommend running Copy in a seperate thread but I think there is enough here to get you pretty far along.
 
0
 
LVL 17

Accepted Solution

by:
AerosSaga earned 500 total points
ID: 11740120
Heres another take:

Option Explicit On Option Strict On

Imports System
Imports System.Net
Imports System.Text

Public Class DownloadWorker
    Private _size As Long
    Private mRead As Long
    Private _status As DownLoadStatus
    Private _errorDescription As String
    Private _sourceURL As String
    Private _destPath As String
    Private _referer As String
    Public Sub New()
        MyBase.new()
        _status = DownLoadStatus.Idle
    End Sub
    Public Sub New(ByVal sSourceURL As String, ByVal sDestPath As String)
        MyBase.new()
        _sourceURL = sSourceURL
        _destPath = sDestPath
    End Sub
    Public Sub New(ByVal sSourceURL As String, ByVal sDestPath As String, ByVal sReferer As String)
        MyBase.new()
        _sourceURL = sSourceURL
        _destPath = sDestPath
        _referer = sReferer
    End Sub

    Public Enum DownLoadStatus
        Idle = 0
        Connecting = 1
        Connected = 2
        Downloading = 3
        Completed = 4
        ErrorOccured = 5
    End Enum

    Public Event StatusChanged(ByRef sender As DownloadWorker, ByVal OldStatus As DownLoadStatus, ByVal NewStatus As DownLoadStatus)
    Public Event ProgressChanged(ByRef sender As DownloadWorker)
    Public Property SourceURL() As String
        Get
            Return _sourceURL
        End Get
        Set(ByVal Value As String)
            Select Case _status
                Case DownLoadStatus.Connected, DownLoadStatus.Connecting, DownLoadStatus.Downloading
                    Throw New InvalidOperationException("SourceURL cannot be changed while download is in progress")
                Case Else
                    _sourceURL = Value
            End Select
        End Set
    End Property
    Public Property DestPath() As String
        Get
            Return _destPath
        End Get
        Set(ByVal Value As String)
            Select Case _status
                Case DownLoadStatus.Connected, DownLoadStatus.Connecting, DownLoadStatus.Downloading
                    Throw New InvalidOperationException("Destination Path cannot be changed while download is in progress")
                Case Else
                    _destPath = Value
            End Select
        End Set
    End Property
    Public Property Referer() As String
        Get
            Return _referer
        End Get
        Set(ByVal Value As String)
            Select Case _status
                Case DownLoadStatus.Connected, DownLoadStatus.Connecting, DownLoadStatus.Downloading
                    Throw New InvalidOperationException("Referer cannot be changed while download is in progress")
                Case Else
                    _referer = Value
            End Select
        End Set
    End Property

    Public ReadOnly Property Status() As DownLoadStatus
        Get
            Return _status
        End Get
    End Property
    Public ReadOnly Property Progress() As Double
        Get
            If _size = 0 Then
                Return 0
            Else
                Return mRead / _size
            End If
        End Get
    End Property
    Public ReadOnly Property Size() As Long
        Get
            Return _size
        End Get
    End Property
    Public ReadOnly Property Downloaded() As Long
        Get
            Return mRead
        End Get
    End Property
    Public ReadOnly Property ErrorDescription() As String
        Get
            Return _errorDescription
        End Get
    End Property
    Private Sub ChangeStatus(ByVal NewStatus As DownLoadStatus)
        Dim Temp As DownLoadStatus
        Temp = _status
        _status = NewStatus
        RaiseEvent StatusChanged(Me, Temp, NewStatus)
    End Sub
    Public Sub DownloadFile()
        Dim bBuffer() As Byte
        Const BlockSize As Integer = 4096
        Dim iRead As Integer
        Dim iReadTotal As Integer
        Dim iTotalSize As Integer
        If _sourceURL = "" Then
            Throw New InvalidOperationException("No Source URL specified")
            Exit Sub
        End If
        If _destPath = "" Then
            Throw New InvalidOperationException("No Destination Path specified")
            Exit Sub
        End If

        Try
            Call ChangeStatus(DownLoadStatus.Connecting)
            Dim wr As HttpWebRequest = CType(WebRequest.Create(_sourceURL), HttpWebRequest)
            If _referer <> "" Then
                wr.Referer = _referer
            End If
            Dim resp As HttpWebResponse = CType(wr.GetResponse(), HttpWebResponse)
            _size = resp.ContentLength
            Call ChangeStatus(DownLoadStatus.Connected)
            Dim sIn As IO.Stream = resp.GetResponseStream
            Dim sOut As New IO.FileStream(_destPath, IO.FileMode.Create)
            ReDim bBuffer(BlockSize - 1)
            Call ChangeStatus(DownLoadStatus.Downloading)
            iRead = sIn.Read(bBuffer, 0, BlockSize)
            mRead = iRead
            While iRead > 0
                RaiseEvent ProgressChanged(Me)
                sOut.Write(bBuffer, 0, iRead)
                iRead = sIn.Read(bBuffer, 0, BlockSize)
                mRead += iRead
            End While
            sIn.Close()
            sOut.Close()
            Call ChangeStatus(DownLoadStatus.Completed)
        Catch ex As Exception
            _errorDescription = ex.Message
            Call ChangeStatus(DownLoadStatus.ErrorOccured)
        End Try
    End Sub

End Class

Regards,

Aeros
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 11740154
yep ... cept you would be copying it yourself (stream to stream) as opposed to downloading it.
0
 
LVL 1

Author Comment

by:Vartana
ID: 11740158
gregoryyoung: i get an errror at

    Private Sub PrepareInfo(ByVal src As String, ByVal dest As String)
        Try
            Dim tododir As CreateDir = New CreateDir(dest)
            Me.Directories.Add(tododir) 'add it for later
            Dim d As DirectoryInfo = New DirectoryInfo(src)
   >>>>>         Dim f As FileInfo() = d.GetFiles()
0
 
LVL 1

Author Comment

by:Vartana
ID: 11740161
System.Exception: Unable to copy ---> System.IO.IOException: The directory name is invalid.

   at System.IO.__Error.WinIOError(Int32 errorCode, String str)
   at System.IO.Directory.InternalGetFileDirectoryNames(String fullPath, String userPath, Boolean file)
   at System.IO.Directory.InternalGetFiles(String path, String userPath, String searchPattern)
   at System.IO.DirectoryInfo.GetFiles(String searchPattern)
   at System.IO.DirectoryInfo.GetFiles()
   at AutoUpdate.FileCopy.PrepareInfo(String src, String dest) in C:\Documents and Settings\vartana\My Documents\Visual Studio Projects\AutoUpdate\Updater.vb:line 308
   --- End of inner exception stack trace ---
   at AutoUpdate.FileCopy.PrepareInfo(String src, String dest) in C:\Documents and Settings\vartana\My Documents\Visual Studio Projects\AutoUpdate\Updater.vb:line 319
   at AutoUpdate.FileCopy.Copy(String src, String dest) in C:\Documents and Settings\vartana\My Documents\Visual Studio Projects\AutoUpdate\Updater.vb:line 326
0
 
LVL 1

Author Comment

by:Vartana
ID: 11740180
lets say its just 1 file.
0
 
LVL 1

Author Comment

by:Vartana
ID: 11740202
ill show the path and the source


\\computer\sharefolder\me.exe to c:\me.exe
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 11740695
with just one file you would want to use Streams to copy if you wanted to show a progressbar ...
0
 
LVL 1

Author Comment

by:Vartana
ID: 11740734
Thnx
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 37

Expert Comment

by:gregoryyoung
ID: 11740740
you would use the size of the stream to generate your maximum and your current position for your status.
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 11740743
btw Vartana my code there is for copying a directory and subdirectories to another directory structure, it was to give you some ideas.
0
 
LVL 1

Author Comment

by:Vartana
ID: 11740745
yeah i got that thank you much....
0
 
LVL 1

Author Comment

by:Vartana
ID: 11740746
No ideas on the other question huh.
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 11740754
the adding of a taskbar ?

you would need to monitor the current running processes, I looked around for a quick example but I was unable to find one. The scope of actually doing that is well out of a question especially if you wanted to support shell extensions like explorer does.
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 11740760
aeros: i am curious why you pass the downloadworker byref in the events ? it would seem that it should be passed byval.
0
 
LVL 1

Author Comment

by:Vartana
ID: 11740761
no  i dont want to support anything, all i want is to emulate the taskbar just the taskbar portion no start menu no clock no systray
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 11740833
ill take a look around see if I can find anything more ...

I believe you will be able to support this mostly through the Process object...
0
 

Expert Comment

by:togo413
ID: 20303701
Can some1 teach me how to access AerosSaga: Class DownloadWorker ?
attached is my code. No working ..

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

    Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        Dim strDestinationPath As String = Application.StartupPath & "\flash"
        Dim strTargetPath As String = "http://cckoay/file_manager_web/flash/merchant/0702010000000003/"
 
        Dim oDW As New DownloadWorker(strTargetPath, strDestinationPath)
        oDW.DownloadFile()
    End Sub
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Article by: Kraeven
Introduction Remote Share is a simple remote sharing tool, enabling you to see, add and remove remote or local shares. The application is written in VB.NET targeting the .NET framework 2.0. The source code and the compiled programs have been in…
It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
This video discusses moving either the default database or any database to a new volume.
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now