Hi all,

I'm trying to display the total extraction progress of a zip file as below.
This gives me the total file size of all uncompressed files in the zip:

For Each backup In zip
                TotalSize = backup.UncompressedSize + TotalSize
            Next

I'm then using this to get the current bytes transfered:

TranferTotal = e.BytesTransferred + TranferTotal

The problem is this value resets after each file is extracted from the zip. I was expecting the above to "tally up" the total so I could use it for the progress bar but it seems to still reset after each item?

Also, I'm using a global varible for the transfer total, if there a better method to transfer this information to the StepEntryProgress?

The reason I'm doing this is because the DotNetZip Library does not support multiple extraction in this way, so I need to tally up in this way.

Code:

Imports Ionic.Zip
Imports System.Threading
Imports System.ComponentModel

Public Class Form1

    Dim TotalSize = 0

    Private _zipBGWorker As System.ComponentModel.BackgroundWorker
    Private Delegate Sub ZipProgress(ByVal e As ExtractProgressEventArgs)
    Private Delegate Sub ExtractEntryProgress(ByVal e As ExtractProgressEventArgs)
    Private Sub BtnUnzip_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnUnzip.Click
        MyExtract()
    End Sub

    Private Sub MyExtract()
        Dim args(2) As String
        args(0) = "C:\Test\Test2.zip"
        args(1) = "C:\Test\ZipTestExtract\"
        _zipBGWorker = New System.ComponentModel.BackgroundWorker()
        _zipBGWorker.WorkerSupportsCancellation = False
        _zipBGWorker.WorkerReportsProgress = False
        AddHandler Me._zipBGWorker.DoWork, New DoWorkEventHandler(AddressOf Me.UnzipFile)
        _zipBGWorker.RunWorkerAsync(args)

    End Sub

    Private Sub UnzipFile(ByVal sender As Object, ByVal e As DoWorkEventArgs)
        Dim extractCancelled As Boolean = False
        Dim args() As String = e.Argument
        Dim ZipToUnpack As String = args(0)
        Dim extractDir As String = args(1)

        Using zip As ZipFile = ZipFile.Read(ZipToUnpack)
            AddHandler zip.ExtractProgress, New EventHandler(Of ExtractProgressEventArgs)(AddressOf Me.zip_ExtractProgress)
            For Each backup In zip
                TotalSize = backup.UncompressedSize + TotalSize
            Next
            For Each backup In zip
                backup.Extract(extractDir, Ionic.Zip.ExtractExistingFileAction.OverwriteSilently)
            Next
        End Using
    End Sub

    Private Sub zip_ExtractProgress(ByVal sender As Object, ByVal e As ExtractProgressEventArgs)
        Me.StepEntryProgress(e)
    End Sub

    Private Sub StepEntryProgress(ByVal e As ExtractProgressEventArgs)

        Dim TranferTotal As Integer
        TranferTotal = e.BytesTransferred + TranferTotal

        If Me.ProgressBar1.InvokeRequired Then
            Me.ProgressBar1.Invoke(New ExtractEntryProgress(AddressOf Me.StepEntryProgress), New Object() {e})
        Else
            Me.ProgressBar1.Maximum = 100
            Me.ProgressBar1.Value = 100 * TranferTotal / TotalSize
            'Me.ProgressBar1.Value = 100 * e.BytesTransferred / e.TotalBytesToTransfer
            Me.LblStatus.Text = CStr(100 * (e.BytesTransferred / e.TotalBytesToTransfer).ToString("#,##0.00")) & "% Complete"

        End If
    End Sub
End Class

many thanks.

Recommended Answers

All 9 Replies

I am not familiar with the zip component you are using. I assume the StepEntryProgress event fires multiple times for multiple files being extracted. Is this correct? If so you are losing your TransferTotal value because it is declared within that subroutine and not globally to the form. Does the progress bar reset with each file before reaching 100%?

Thanks,
Kenny

Hi Kenny, yes it does.
My TransferTotal seems to reset to 0 after each file extract:

TranferTotal = e.BytesTransferred + TranferTotal

Am I adding to the existing value wrong?

At the top where you declare Dim TotalSize = 0, add another declaration for TransferTotal. Then in the section of code below delete this line:

Dim TransferTotal As Integer

Private Sub StepEntryProgress(ByVal e As ExtractProgressEventArgs)

        Dim TranferTotal As Integer
        TranferTotal = e.BytesTransferred + TranferTotal

        If Me.ProgressBar1.InvokeRequired Then
            Me.ProgressBar1.Invoke(New ExtractEntryProgress(AddressOf Me.StepEntryProgress), New Object() {e})
        Else
            Me.ProgressBar1.Maximum = 100
            Me.ProgressBar1.Value = 100 * TranferTotal / TotalSize
            'Me.ProgressBar1.Value = 100 * e.BytesTransferred / e.TotalBytesToTransfer
            Me.LblStatus.Text = CStr(100 * (e.BytesTransferred / e.TotalBytesToTransfer).ToString("#,##0.00")) & "% Complete"

        End If
    End Sub

This will make the TransferTotal also a global variable to the class and it shouldn't reset back to zero with each file. Let me know if this is not the case and I will take a closer look at your code.

Thanks,
Kenny

Values after extracting 3 files:
TotalSize = 305150464 (Which is correct for the total size of all files)
TransferTotal = 2447309139968 (I expected it to total TotalSize?)

Values after extracting first file:
BytesToTransfer = 56378880 for the first file (Which is correct)
Transfer Total = 97109969920 in relation to the above value... Not sure how it's getting this figure... Should be the same?

Let me take a closer look at your code.

Kenny

Is it because BytesTransferred is updating on every event its adding the number at that point multiple times a second?

I still have to stand by my other post. I can't run the code but does this not work?

Imports Ionic.Zip
Imports System.Threading
Imports System.ComponentModel

Public Class Form1

    Dim TotalSize = 0
    Dim TranferTotal As Integer = 0

    Private _zipBGWorker As System.ComponentModel.BackgroundWorker
    Private Delegate Sub ZipProgress(ByVal e As ExtractProgressEventArgs)
    Private Delegate Sub ExtractEntryProgress(ByVal e As ExtractProgressEventArgs)
    Private Sub BtnUnzip_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnUnzip.Click
        MyExtract()
    End Sub

    Private Sub MyExtract()
        Dim args(2) As String
        args(0) = "C:\Test\Test2.zip"
        args(1) = "C:\Test\ZipTestExtract\"
        _zipBGWorker = New System.ComponentModel.BackgroundWorker()
        _zipBGWorker.WorkerSupportsCancellation = False
        _zipBGWorker.WorkerReportsProgress = False
        AddHandler Me._zipBGWorker.DoWork, New DoWorkEventHandler(AddressOf Me.UnzipFile)
        _zipBGWorker.RunWorkerAsync(args)

    End Sub

    Private Sub UnzipFile(ByVal sender As Object, ByVal e As DoWorkEventArgs)
        Dim extractCancelled As Boolean = False
        Dim args() As String = e.Argument
        Dim ZipToUnpack As String = args(0)
        Dim extractDir As String = args(1)

        Using zip As ZipFile = ZipFile.Read(ZipToUnpack)
            AddHandler zip.ExtractProgress, New EventHandler(Of ExtractProgressEventArgs)(AddressOf Me.zip_ExtractProgress)
            For Each backup In zip
                TotalSize = backup.UncompressedSize + TotalSize
            Next
            For Each backup In zip
                backup.Extract(extractDir, Ionic.Zip.ExtractExistingFileAction.OverwriteSilently)
            Next
        End Using
    End Sub

    Private Sub zip_ExtractProgress(ByVal sender As Object, ByVal e As ExtractProgressEventArgs)
        Me.StepEntryProgress(e)
    End Sub

    Private Sub StepEntryProgress(ByVal e As ExtractProgressEventArgs)

        TranferTotal = e.BytesTransferred + TranferTotal

        If Me.ProgressBar1.InvokeRequired Then
            Me.ProgressBar1.Invoke(New ExtractEntryProgress(AddressOf Me.StepEntryProgress), New Object() {e})
        Else
            Me.ProgressBar1.Maximum = 100
            Me.ProgressBar1.Value = 100 * TranferTotal / TotalSize
            'Me.ProgressBar1.Value = 100 * e.BytesTransferred / e.TotalBytesToTransfer
            Me.LblStatus.Text = CStr(100 * (e.BytesTransferred / e.TotalBytesToTransfer).ToString("#,##0.00")) & "% Complete"

        End If
    End Sub
End Class

The only thing I can think of is the TransferTotal is resetting to zero with each file due to not being global.....

Kenny

Is it because BytesTransferred is updating on every event its adding the number at that point multiple times a second?

It looks like TransferTotal is to hold the total bytes transferred across all files right?

If thats true and StepEntryProgress fires for each file your declaration of a local variable TranferTotal resets to zero for each file.

If you have a routine like this:

Private Sub Test()
       Dim x As Integer

       x = x + 5
    End Sub

x will always have a value of 5 because its scope is only defined within that sub Test. Once execution exits the subroutine the value is gone.

In your case TranferTotal is defined within a sub routine and if it is called with each file being extracted or more the value resets everytime it is called. Technically not even reset. The variable doesn't exist outside the subroutine so every call is a new instance.

Does this make sense?

Kenny

I may be wrong as I have never used the zip component but looking at your code again I see nothing else that would cause this behaviour.

Kenny

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.