Save Files and use Progressbar

Apr 26, 2011 at 11:44 AM
Edited Apr 26, 2011 at 11:44 AM

Hi Guys,

First of all, the Library is great.

Now my problem: I'm using VB.NET and I try to add files to specific folders in the ZipFile (named zip1). This adding works.

I catched the Example of zipping Directory and showing Progressbars. This example works great for me.

But when I change the AddDirectory-Method with a for loop and the AddItem method, the Invoke method of ProgressBar1 in the StepArchiveProgress method gets an ArgumentOutOfRangeException ("Value is -1").

This happens when the zip1_SaveProgress gets the "Saving_AfterWriteEntry" Event

Here is my code:

 

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

Public Class frmExport

    Private _backgroundWorker1 As System.ComponentModel.BackgroundWorker
    Private _saveCanceled As Boolean
    Private _totalBytesAfterCompress As Long
    Private _totalBytesBeforeCompress As Long
    Private _nFilesCompleted As Integer
    Private _progress2MaxFactor As Integer
    Private _entriesToZip As Integer

    Private _DirToZip As String = ""
    Private _ZipToCreate As String = ""
    Private _files(,) As String

    Private modus As Integer = 0 ' 0 - Files, 1 - Directory

    ' Delegates for invocation of UI from other threads
    Private Delegate Sub SaveEntryProgress(ByVal e As SaveProgressEventArgs)
    Private Delegate Sub ButtonClick(ByVal sender As Object, ByVal e As EventArgs)

    Public Sub setFolders(ByVal folder As String, ByVal destination As String)
        _DirToZip = folder
        _ZipToCreate = destination
    End Sub

    Public Sub setFileList(ByVal fileList(,) As String, ByVal destination As String)
        _ZipToCreate = destination
        _files = fileList

    End Sub



    Public Sub Export(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Me.Load

        Select Case modus
            Case 0
                ' Files
                Me.ZipFiles()
            Case 1
                ' Directory
                Me.ZipFolder()
        End Select


    End Sub
    Private Sub ZipFiles()
        If ((Not _ZipToCreate Is Nothing) AndAlso (_ZipToCreate <> "")) Then
            If File.Exists(_ZipToCreate) Then
                If (MessageBox.Show(String.Format("The file you have specified ({0}) already exists.  Do you want to overwrite this file?", _
                                                  _ZipToCreate), "Confirmation is Required", _
                                                  MessageBoxButtons.YesNo, MessageBoxIcon.Question) <> DialogResult.Yes) Then
                    Return
                End If
                File.Delete(_ZipToCreate)
            End If
            Me._saveCanceled = False
            Me._nFilesCompleted = 0
            Me._totalBytesAfterCompress = 0
            Me._totalBytesBeforeCompress = 0
            Me.btnCancel.Enabled = True
            Me.lblStatus.Text = "Zipping..."
            Dim options As New WorkerOptions
            options.ZipName = _ZipToCreate

            _backgroundWorker1 = New System.ComponentModel.BackgroundWorker()
            _backgroundWorker1.WorkerSupportsCancellation = False
            _backgroundWorker1.WorkerReportsProgress = False
            AddHandler Me._backgroundWorker1.DoWork, New DoWorkEventHandler(AddressOf Me.DoSave)
            _backgroundWorker1.RunWorkerAsync(options)

        End If
    End Sub

    Private Sub ZipFolder()
        Try
            Dim folderName As String = _DirToZip
            If (((Not folderName Is Nothing) AndAlso (folderName <> "")) AndAlso ((Not _ZipToCreate Is Nothing) AndAlso (_ZipToCreate <> ""))) Then
                If File.Exists(_ZipToCreate) Then
                    If (MessageBox.Show(String.Format("The file you have specified ({0}) already exists.  Do you want to overwrite this file?", _
                                                      _ZipToCreate), "Confirmation is Required", _
                                                      MessageBoxButtons.YesNo, MessageBoxIcon.Question) <> DialogResult.Yes) Then
                        Return
                    End If
                    File.Delete(_ZipToCreate)
                End If
                Me._saveCanceled = False
                Me._nFilesCompleted = 0
                Me._totalBytesAfterCompress = 0
                Me._totalBytesBeforeCompress = 0
                Me.btnCancel.Enabled = True
                Me.lblStatus.Text = "Zipping..."
                Dim options As New WorkerOptions
                options.ZipName = _ZipToCreate
                options.Folder = folderName

                _backgroundWorker1 = New System.ComponentModel.BackgroundWorker()
                _backgroundWorker1.WorkerSupportsCancellation = False
                _backgroundWorker1.WorkerReportsProgress = False
                AddHandler Me._backgroundWorker1.DoWork, New DoWorkEventHandler(AddressOf Me.DoSave)
                _backgroundWorker1.RunWorkerAsync(options)

            End If
        Catch ex As Exception

        End Try
        
    End Sub


    Private Sub DoSave(ByVal sender As Object, ByVal e As DoWorkEventArgs)
        Dim options As WorkerOptions = e.Argument
        Try
            Using zip1 As ZipFile = New ZipFile
                Select Case modus
                    Case 0
                        ' Files to add to current Project

                        Dim i As Integer
                        For i = 0 To _files.GetUpperBound(0)
                            ' will add Files or Dirs, recursing and flattening subdirectories.
                            zip1.AddItem(_files(i, 1), _files(i, 0))
                        Next i
                    Case 1
                        ' Directory
                        zip1.AddDirectory(options.Folder)
                End Select
                
                Me._entriesToZip = zip1.EntryFileNames.Count
                Me.SetProgressBars()
                AddHandler zip1.SaveProgress, New EventHandler(Of SaveProgressEventArgs)(AddressOf Me.zip1_SaveProgress)
                zip1.Save(options.ZipName)
            End Using
        Catch exc1 As Exception
            MessageBox.Show(String.Format("Exception while zipping: {0}", exc1.Message))
            Me.btnCancel_Click(Nothing, Nothing)
        End Try
    End Sub


    Private Sub zip1_SaveProgress(ByVal sender As Object, ByVal e As SaveProgressEventArgs)
        If Me._saveCanceled Then
            e.Cancel = True
            Return
        End If

        Select Case e.EventType
            Case ZipProgressEventType.Saving_AfterWriteEntry
                Me.StepArchiveProgress(e)
                Exit Select
            Case ZipProgressEventType.Saving_Completed
                Me.SaveCompleted()
                Exit Select
            Case ZipProgressEventType.Saving_EntryBytesRead
                Me.StepEntryProgress(e)
                Exit Select
            Case Else
                MsgBox(Me.ProgressBar1.Value)
        End Select
    End Sub



    Private Sub StepArchiveProgress(ByVal e As SaveProgressEventArgs)
        If Me.ProgressBar1.InvokeRequired Then
            Me.ProgressBar1.Invoke(New SaveEntryProgress(AddressOf Me.StepArchiveProgress), New Object() {e})
        ElseIf Not Me._saveCanceled Then
            Me._nFilesCompleted += 1
            Me.ProgressBar1.PerformStep()
            Me._totalBytesAfterCompress = (Me._totalBytesAfterCompress + e.CurrentEntry.CompressedSize)
            Me._totalBytesBeforeCompress = (Me._totalBytesBeforeCompress + e.CurrentEntry.UncompressedSize)
            ' progressBar2 is the one dealing with the item being added to the archive
            ' if we got this event, then the add of that item (or file) is complete, so we 
            ' update the progressBar2 appropriately.
            Me.ProgressBar2.Value = Me.ProgressBar2.Maximum = 1
            MyBase.Update()
        End If
    End Sub


    Private Sub SaveCompleted()
        If Me.lblStatus.InvokeRequired Then
            Me.lblStatus.Invoke(New MethodInvoker(AddressOf SaveCompleted))
            'Me.lblStatus.Invoke(New MethodInvoker(Me, DirectCast(Me.SaveCompleted, IntPtr)))
        Else
            Me.lblStatus.Text = String.Format("Done, Compressed {0} files, {1:N0}% of original", Me._nFilesCompleted, ((100 * Me._totalBytesAfterCompress) / CDbl(Me._totalBytesBeforeCompress)))
            Me.ResetState()
            Me.Close()
        End If
    End Sub


    Private Sub StepEntryProgress(ByVal e As SaveProgressEventArgs)
        If Me.ProgressBar2.InvokeRequired Then
            Me.ProgressBar2.Invoke(New SaveEntryProgress(AddressOf Me.StepEntryProgress), New Object() {e})
        ElseIf Not Me._saveCanceled Then
            If (Me.ProgressBar2.Maximum = 1) Then
                Dim entryMax As Long = e.TotalBytesToTransfer
                Dim absoluteMax As Long = &H7FFFFFFF
                Me._progress2MaxFactor = 0
                Do While (entryMax > absoluteMax)
                    entryMax = (entryMax / 2)
                    Me._progress2MaxFactor += 1
                Loop
                If (CInt(entryMax) < 0) Then
                    entryMax = (entryMax * -1)
                End If
                Me.ProgressBar2.Maximum = CInt(entryMax)
                Me.lblStatus.Text = String.Format("{0} of {1} files...({2})", (Me._nFilesCompleted + 1), Me._entriesToZip, e.CurrentEntry.FileName)
            End If
            Dim xferred As Integer = CInt((e.BytesTransferred >> Me._progress2MaxFactor))
            Me.ProgressBar2.Value = IIf((xferred >= Me.ProgressBar2.Maximum), Me.ProgressBar2.Maximum, xferred)
            Me.lblStatus.Text = String.Format("{0} of {1} files...({2})", (Me._nFilesCompleted + 1), Me._entriesToZip, e.CurrentEntry.FileName)
            MyBase.Update()
        End If
    End Sub


    Private Sub ResetState()
        Me.btnCancel.Enabled = False
        Me.ProgressBar1.Value = 0
        Me.ProgressBar2.Value = 0
        Me.Cursor = Cursors.Default
    End Sub



    Private Sub SetProgressBars()
        If Me.ProgressBar1.InvokeRequired Then
            'Me.ProgressBar1.Invoke(New MethodInvoker(Me, DirectCast(Me.SetProgressBars, IntPtr)))
            Me.ProgressBar1.Invoke(New MethodInvoker(AddressOf SetProgressBars))
        Else
            Me.ProgressBar1.Value = 0
            Me.ProgressBar1.Maximum = Me._entriesToZip
            Me.ProgressBar1.Minimum = 0
            Me.ProgressBar1.Step = 1
            Me.ProgressBar2.Value = 0
            Me.ProgressBar2.Minimum = 0
            Me.ProgressBar2.Maximum = 1
            Me.ProgressBar2.Step = 2
        End If
    End Sub


    Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
        If Me.lblStatus.InvokeRequired Then
            Me.lblStatus.Invoke(New ButtonClick(AddressOf Me.btnCancel_Click), New Object() {sender, e})
        Else
            Me._saveCanceled = True
            Me.lblStatus.Text = "Canceled..."
            Me.ResetState()
            Me.Close()
        End If
    End Sub

End Class

Public Class WorkerOptions
    ' Fields
    'Public Comment As String
    'Public CompressionLevel As CompressionLevel
    'Public Encoding As String
    'Public Encryption As EncryptionAlgorithm
    Public Folder As String
    'Public Password As String
    'Public Zip64 As Zip64Option
    'Public ZipFlavor As Integer
    Public ZipName As String
End Class

 

Can you see any mistake or can you give me an example, which shows how to zip files using progressbars?

Apr 27, 2011 at 9:55 AM

I already figured out, there is a problem with this:

Me.ProgressBar2.Maximum = 1
Me.ProgressBar2.Step = 2

When I set the Maximum to 2 and the Step to 1, it seems to work.