Copy a file with progressbar in VB.NET
Today I wanted to create a control that could copy files in VB.NET with some progress indication. I did some searches on the Internet and managed to build a working control. However, I would like to share the basics with all of you...
First declare some API functions:
Private Delegate Function CopyProgressRoutine(ByVal totalFileSize As Int64, ByVal totalBytesTransferred As Int64, ByVal streamSize As Int64, ByVal streamBytesTransferred As Int64, ByVal dwStreamNumber As Int32, ByVal dwCallbackReason As Int32, ByVal hSourceFile As Int32, ByVal hDestinationFile As Int32, ByVal lpData As Int32) As Int32
Private Declare Auto Function CopyFileEx Lib "kernel32.dll" (ByVal lpExistingFileName As String, ByVal lpNewFileName As String, ByVal lpProgressRoutine As CopyProgressRoutine, ByVal lpData As Int32, ByVal lpBool As Int32, ByVal dwCopyFlags As Int32) As Int32
Add a button (Button1) to your form and add this code to the Click event:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim cpr As New CopyProgressRoutine(AddressOf CopyProgress)
CopyFileEx("C:\Program Files\Common Files\Microsoft Shared\DAO\dao360.dll", "C:\dao360_delete.dll", cpr, 0, 0, 0)
End Sub
Make sure the file exists on your filesystem, I advise you to take a big file (> 100MB) to see the progressbar working...
Add a ProgressBar (ProgressBar1) to your form and create a function called CopyProgress:
Private Function CopyProgress(ByVal totalFileSize As Int64, ByVal totalBytesTransferred As Int64, ByVal streamSize As Int64, ByVal streamBytesTransferred As Int64, ByVal dwStreamNumber As Int32, ByVal dwCallbackReason As Int32, ByVal hSourceFile As Int32, ByVal hDestinationFile As Int32, ByVal lpData As Int32) As Int32
ProgressBar1.Value = Convert.ToInt32(TotalBytesTransferred / TotalFileSize * 100)
End Function
Click the button and watch the spectacle ;-)
CopyFileEx will return a nonzero value in case of success, it will return 0 in case of error. Use this code to retrieve the error information:
Dim copyError As Exception = New System.ComponentModel.Win32Exception(System.Runtime.InteropServices.Marshal.GetLastWin32Error)
If you want to cancel the copy process and delete the new file, make sure CopyProgress returns PROGRESS_CANCEL
Private Const PROGRESS_CANCEL As Integer = 1
This function will overwrite an existing file by default. If you don't want this to happen, change the function call to
Private Const COPY_FILE_FAIL_IF_EXISTS As Integer = 1
CopyFileEx("C:\Program Files\Common Files\Microsoft Shared\DAO\dao360.dll", "C:\dao360_delete.dll", cpr, 0, 0, COPY_FILE_FAIL_IF_EXISTS)
Copying will fail if the file has the Hidden or the Readonly attribute. Use this code to reset the attributes to Normal:
Dim fi As New System.IO.FileInfo(destinationFileName)
If fi.Exists Then
fi.Attributes = IO.FileAttributes.Normal
End If
First declare some API functions:
Private Delegate Function CopyProgressRoutine(ByVal totalFileSize As Int64, ByVal totalBytesTransferred As Int64, ByVal streamSize As Int64, ByVal streamBytesTransferred As Int64, ByVal dwStreamNumber As Int32, ByVal dwCallbackReason As Int32, ByVal hSourceFile As Int32, ByVal hDestinationFile As Int32, ByVal lpData As Int32) As Int32
Private Declare Auto Function CopyFileEx Lib "kernel32.dll" (ByVal lpExistingFileName As String, ByVal lpNewFileName As String, ByVal lpProgressRoutine As CopyProgressRoutine, ByVal lpData As Int32, ByVal lpBool As Int32, ByVal dwCopyFlags As Int32) As Int32
Add a button (Button1) to your form and add this code to the Click event:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim cpr As New CopyProgressRoutine(AddressOf CopyProgress)
CopyFileEx("C:\Program Files\Common Files\Microsoft Shared\DAO\dao360.dll", "C:\dao360_delete.dll", cpr, 0, 0, 0)
End Sub
Make sure the file exists on your filesystem, I advise you to take a big file (> 100MB) to see the progressbar working...
Add a ProgressBar (ProgressBar1) to your form and create a function called CopyProgress:
Private Function CopyProgress(ByVal totalFileSize As Int64, ByVal totalBytesTransferred As Int64, ByVal streamSize As Int64, ByVal streamBytesTransferred As Int64, ByVal dwStreamNumber As Int32, ByVal dwCallbackReason As Int32, ByVal hSourceFile As Int32, ByVal hDestinationFile As Int32, ByVal lpData As Int32) As Int32
ProgressBar1.Value = Convert.ToInt32(TotalBytesTransferred / TotalFileSize * 100)
End Function
Click the button and watch the spectacle ;-)
CopyFileEx will return a nonzero value in case of success, it will return 0 in case of error. Use this code to retrieve the error information:
Dim copyError As Exception = New System.ComponentModel.Win32Exception(System.Runtime.InteropServices.Marshal.GetLastWin32Error)
If you want to cancel the copy process and delete the new file, make sure CopyProgress returns PROGRESS_CANCEL
Private Const PROGRESS_CANCEL As Integer = 1
This function will overwrite an existing file by default. If you don't want this to happen, change the function call to
Private Const COPY_FILE_FAIL_IF_EXISTS As Integer = 1
CopyFileEx("C:\Program Files\Common Files\Microsoft Shared\DAO\dao360.dll", "C:\dao360_delete.dll", cpr, 0, 0, COPY_FILE_FAIL_IF_EXISTS)
Copying will fail if the file has the Hidden or the Readonly attribute. Use this code to reset the attributes to Normal:
Dim fi As New System.IO.FileInfo(destinationFileName)
If fi.Exists Then
fi.Attributes = IO.FileAttributes.Normal
End If
17 Comments:
Very nice, just what I was looking for.
By Anonymous, at 4:13 PM
This code is very useful and very efficient. It look like VB05 still missing some basic function like this CopyFileEx(). Maybe one day (in VB99) we will get all what it's need to write window application...
By Anonymous, at 2:33 AM
Thank your for your comment!
I always loved to play around with API-calls in the old VB-days... I think the .NET framework has already a lot embedded.
By kHSw, at 11:06 PM
hello there.
thanks for the snippet ..
was useful
was searching for overwrite with readonly attr
thanks dude
By Anonymous, at 12:16 PM
Thanks!
By kHSw, at 12:21 AM
Very nice and very clean. Thanks for the snippet.
By Anonymous, at 5:39 PM
wow..it works..after 30 minutes of searching..
then i found this solution..
Thanks a lot Bro..!!
By Anonymous, at 2:26 PM
there is any cancel procedure?
Nice piece of code.. but the cancel is missing only there...
By Anonymous, at 2:59 PM
Thanks... Really helpful
Naveed A. Ghani
By Anonymous, at 8:23 AM
Really helpfull, I was looking for it !
But how can I do to do it in multithreading ? Because during the file is copied and the progress bar is progressing the program is frozen...
Thanks for your help
By Anonymous, at 2:28 PM
Is there any way to make something like this in VB 6 ?
By alam.pramono, at 9:17 AM
Why My ProgressBar doesn't response at all. My ProgressBar only response at my file is completely copied.
Is your code using BackgroundWorker class ?
Thx for any help...
By Anonymous, at 10:56 AM
This is a brilliant article been looking for something like this for days.
By Anonymous, at 6:15 PM
I don' understand how to use PROGRESS_CANCEL
By Anonymous, at 3:59 PM
Year 2009, and it's still very useful!
Many thanks!!!!
By Ivaneck, at 5:28 PM
Very nice - used this in some of my vb6 projects. :)
btw to the posters above looking for a more .net like solution: You can find a fully .net-ified example implemented as a static class here.
By dePoPo, at 12:16 PM
Nice Work. It actually works!
By Anonymous, at 3:44 PM
Post a Comment
<< Home