.comment-link {margin-left:.6em;}

kHSw

Wednesday, August 03, 2005

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

17 Comments:

  • Very nice, just what I was looking for.

    By Anonymous 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 Dreamer, 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 Blogger kHSw, at 11:06 PM  

  • hello there.

    thanks for the snippet ..
    was useful
    was searching for overwrite with readonly attr

    thanks dude

    By Blogger Reeba, at 12:16 PM  

  • Thanks!

    By Blogger kHSw, at 12:21 AM  

  • Very nice and very clean. Thanks for the snippet.

    By Anonymous Anonymous, at 5:39 PM  

  • wow..it works..after 30 minutes of searching..

    then i found this solution..

    Thanks a lot Bro..!!

    By Anonymous Anonymous, at 2:26 PM  

  • there is any cancel procedure?
    Nice piece of code.. but the cancel is missing only there...

    By Anonymous Anonymous, at 2:59 PM  

  • Thanks... Really helpful

    Naveed A. Ghani

    By Anonymous 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 Anonymous, at 2:28 PM  

  • Is there any way to make something like this in VB 6 ?

    By Blogger scarecrow, 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 Anonymous, at 10:56 AM  

  • This is a brilliant article been looking for something like this for days.

    By Anonymous Anonymous, at 6:15 PM  

  • I don' understand how to use PROGRESS_CANCEL

    By Anonymous Anonymous, at 3:59 PM  

  • Year 2009, and it's still very useful!

    Many thanks!!!!

    By Blogger 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 Anonymous dePoPo, at 12:16 PM  

  • Nice Work. It actually works!

    By Anonymous Anonymous, at 3:44 PM  

Post a Comment

Links to this post:

Create a Link

<< Home


 
Stefanie Worm is het liefste vrouwtje van de wereld.
Melina is de liefste schatsie van de wereld (Erik De Maeyer).