none
VB.NET Compress & Extract Zip with Progress Bar RRS feed

  • Question

  • Hi,

    I have files in a folder "test" and i want to make a zip of the contents(not the folder) and have that zip in the directory of the folder.

    Sor far, all is well:

            Dim curentDate As String = System.DateTime.Now.ToShortDateString
            Dim gamepath As String = TextBox1.Text
            Dim zipPath As String = gamepath + "backup" + curentDate + ".zip"
            Dim extractPath As String = "gamepath"
    
    'zip
            ZipFile.CreateFromDirectory(gamepath, zipPath)
    'extract
            ZipFile.ExtractToDirectory(zipPath, extractPath)

    But, how do I add a progress bar and a percentage label? I don't mind if the percentage has decimals as long as it's only to 2 decimal points. 

    Thanks so much,

    David Wu

    Wednesday, January 22, 2014 5:37 AM

Answers

  • You'll have to extract each file individually so that you have a chance to update the progress bar.   Keep in mind that the process is likely to occur much faster than the progressbar can actually update unless the archive is very large.

    Here's a brief example of one way to do it:

    'Add references to:
    '  System.IO.Compression
    '  System.IO.Compression.FileSystem
    Imports System.IO
    Imports System.IO.Compression
    
    Public Class Form1
        Friend ProgressBar1 As New ProgressBar
        Friend WithEvents Button1 As New Button With {.Top = ProgressBar1.Height + 4}
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Controls.Add(ProgressBar1)
            Controls.Add(Button1)
        End Sub
    
        Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Button1.Enabled = False
            Await ExtractAllAsync("c:\test\test.zip", "c:\test\test extract", ProgressBar1)
            Button1.Enabled = True
        End Sub
    
        Private Async Function ExtractAllAsync(zipFilePath As String, extractPath As String, progress As ProgressBar) As Task
            Try
                Dim extractCount, skipCount, errorCount As Integer
                Using archive As ZipArchive = ZipFile.OpenRead(zipFilePath)
                    progress.Minimum = 0
                    progress.Maximum = archive.Entries.Count
                    Await Task.Run(Sub()
                                       Dim count As Integer = archive.Entries.Count
                                       For i As Integer = 0 To count - 1
                                           Try
                                               Dim entry As ZipArchiveEntry = archive.Entries(i)
                                               entry.ExtractToFile(Path.Combine(extractPath, entry.FullName))
                                               extractCount += 1
                                           Catch ioex As IOException
                                               If ioex.Message.EndsWith("already exists.") Then
                                                   skipCount += 1
                                               Else
                                                   errorCount += 1
                                               End If
                                           Catch ex As Exception
                                               errorCount += 1
                                           End Try
                                           Invoke(Sub() progress.Value += 1)
                                           'System.Threading.Thread.Sleep(100) 'might want delay to see progress animation better
                                       Next
                                       'System.Threading.Thread.Sleep(100)
                                   End Sub)
                End Using
                MessageBox.Show(String.Format("Extracted {0} files, skipping {1} because they exist, with {2} errors.", extractCount, skipCount, errorCount), "Extraction Complete", MessageBoxButtons.OK, MessageBoxIcon.Information)
                progress.Value = 0
            Catch ex As Exception
                MessageBox.Show(ex.Message, "Error Opening Zip File", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End Try
        End Function
    End Class


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"


    Wednesday, January 22, 2014 8:10 PM
    Moderator
  • Well I changed it by using some timers.

    Although it seems to me that backgroundworkers are passing variables that were created in another thread information without crossthread issues. So I'm not sure why a background worker can pass a variable information but not a control information without a crossthread issue.

    This code is pretty much in line with what Noodles LV proposed.

    I'll post some images a bit later.

    Option Strict On
    
    ' NOTE: Only works with .Net 4.5 or above. Compile to .Net 4.5 or above.
    ' Also crashes if you attempt to zip a shortcut.
    
    Imports System.IO
    Imports System.IO.Compression ' Add reference to this in Assemblies as well as a reference to System.IO.Compression.FileSystem I think.
    
    Public Class Form1
    
        ' How to: Compress and Extract Files http://msdn.microsoft.com/en-us/library/ms404280(v=vs.110).aspx
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.CenterToScreen()
            Me.BackColor = Color.PapayaWhip
            Me.Text = "Zip and Unzip files using .Net 4.5 System.IO.Compression"
            Button1.BackColor = Color.Lime
            Button2.BackColor = Color.Lime
            Button3.BackColor = Color.Lime
            Button4.BackColor = Color.LightGray
            Button4.Enabled = False
            ProgressBar1.Minimum = 0
            ProgressBar1.Maximum = 100
            Label1.Text = "Waiting"
            Label2.Text = "Waiting"
            ListView1.MultiSelect = False
            ListView1.GridLines = True
            ListView1.LabelEdit = True
            ListView1.UseCompatibleStateImageBehavior = False
            ListView1.View = View.Details
            ListView1.Sorting = SortOrder.Ascending
            ListView1.Columns.Add("Files to be Zipped", 434, HorizontalAlignment.Left)
            Timer1.Interval = 1
            Timer2.Interval = 1
        End Sub
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Button1.Enabled = False
            Button2.Enabled = False
            Button3.Enabled = False
            Button1.BackColor = Color.OrangeRed
            Button2.BackColor = Color.LightGray
            Button3.BackColor = Color.LightGray
            Dim SFD As New SaveFileDialog
            SFD.Title = "Create Zip file. Type in name (i.e. ZipFile), do not add .Zip extension."
            SFD.InitialDirectory = "C:\Users\John\Desktop"
            SFD.DefaultExt = ""
            SFD.Filter = "Zip Files (*.Zip)|*.Zip"
            If SFD.ShowDialog = Windows.Forms.DialogResult.OK Then
                My.Computer.FileSystem.CreateDirectory(SFD.FileName.ToString.Replace(".Zip", ""))
                ZipFile.CreateFromDirectory(SFD.FileName.ToString.Replace(".Zip", ""), SFD.FileName)
                If My.Computer.FileSystem.DirectoryExists(SFD.FileName.ToString.Replace(".Zip", "")) Then
                    My.Computer.FileSystem.DeleteDirectory(SFD.FileName.ToString.Replace(".Zip", ""), FileIO.DeleteDirectoryOption.DeleteAllContents)
                End If
            End If
            Button1.Enabled = True
            Button2.Enabled = True
            Button3.Enabled = True
            Button1.BackColor = Color.Lime
            Button2.BackColor = Color.Lime
            Button3.BackColor = Color.Lime
        End Sub
    
    
        Dim FilesToZipSize As Integer = 0
        Dim FileInfo() As String
        Dim ZipFiletoUse As String = ""
    
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            Button1.Enabled = False
            Button2.Enabled = False
            Button3.Enabled = False
            Button1.BackColor = Color.LightGray
            Button2.BackColor = Color.OrangeRed
            Button3.BackColor = Color.LightGray
    
            Dim OFD1 As New OpenFileDialog
            OFD1.Title = "Select Zip file to use"
            OFD1.InitialDirectory = "C:\Users\John\Desktop"
            OFD1.Filter = "Zip Files (*.Zip)|*.Zip"
            OFD1.Multiselect = False
    
            Dim OFD2 As New OpenFileDialog
            OFD2.Title = "Select files to Zip"
            OFD2.Multiselect = True
            OFD2.InitialDirectory = "C:\Users\John\Desktop"
            OFD2.Filter = "All Files|*.*"
    
            If OFD1.ShowDialog = Windows.Forms.DialogResult.OK Then
                ZipFileToUse = OFD1.FileName
                If OFD2.ShowDialog = Windows.Forms.DialogResult.OK Then
                    For Each Item In OFD2.FileNames
                        FilesToZipSize += CInt(FileLen(Item))
                        ListView1.Items.Add(Item)
                    Next
                    FileInfo = OFD2.FileNames
                    BGW1Active = True
                    Timer1.Start()
                    ProgressBar1.Value = 0
                    BackgroundWorker1.RunWorkerAsync()
                End If
            End If
        End Sub
    
        Dim ZipFolderToUnzipFilesFrom As String = ""
    
        Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
            Button1.Enabled = False
            Button2.Enabled = False
            Button3.Enabled = False
            Button1.BackColor = Color.LightGray
            Button2.BackColor = Color.LightGray
            Button3.BackColor = Color.OrangeRed
            CheckedListBox1.Items.Clear()
            Dim OFD As New OpenFileDialog
            OFD.Title = "Select Zip folder to use"
            OFD.InitialDirectory = "C:\Users\John\Desktop"
            OFD.Filter = "Zip Files (*.Zip)|*.Zip"
            OFD.Multiselect = False
            If OFD.ShowDialog = Windows.Forms.DialogResult.OK Then
                ZipFolderToUnzipFilesFrom = OFD.FileName
                Using archive As ZipArchive = ZipFile.OpenRead(OFD.FileName)
                    For Each entry As ZipArchiveEntry In archive.Entries
                        CheckedListBox1.Items.Add(entry.ToString)
                    Next
                End Using
                If CheckedListBox1.Items.Count = 0 Then
                    Button1.Enabled = True
                    Button2.Enabled = True
                    Button3.Enabled = True
                    Button1.BackColor = Color.Lime
                    Button2.BackColor = Color.Lime
                    Button3.BackColor = Color.Lime
                End If
            End If
    
        End Sub
    
        Private Sub CheckedListBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles CheckedListBox1.SelectedIndexChanged
            If CheckedListBox1.CheckedItems.Count > 0 Then
                Button4.Enabled = True
                Button4.BackColor = Color.Lime
            End If
        End Sub
    
        Dim FolderToUnzipFilesTo As String = ""
        Dim FilesToUnzipSize As Integer = 0
    
        Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
            Button3.BackColor = Color.LightGray
            If CheckedListBox1.CheckedItems.Count = 0 Then
                Button1.Enabled = True
                Button2.Enabled = True
                Button3.Enabled = True
                Button1.BackColor = Color.Lime
                Button2.BackColor = Color.Lime
            Else
                Button4.Enabled = False
                Button4.BackColor = Color.OrangeRed
                Dim FBD As New FolderBrowserDialog
                FBD.Description = "Select folder or create folder to unzip file(s) to"
                FBD.RootFolder = Environment.SpecialFolder.Desktop
                If FBD.ShowDialog = Windows.Forms.DialogResult.OK Then
                    FolderToUnzipFilesTo = FBD.SelectedPath
                    Using archive As ZipArchive = ZipFile.OpenRead(ZipFolderToUnzipFilesFrom)
                        For Each Item In CheckedListBox1.CheckedItems
                            For Each entry As ZipArchiveEntry In archive.Entries
                                If entry.FullName.ToString = Item.ToString Then
                                    FilesToUnzipSize += CInt(entry.Length)
                                End If
                            Next
                        Next
                    End Using
                    BGW2Active = True
                    Timer2.Start()
                    ProgressBar1.Value = 0
                    BackgroundWorker2.RunWorkerAsync()
                Else
                    Button1.Enabled = True
                    Button2.Enabled = True
                    Button3.Enabled = True
                    Button1.BackColor = Color.Lime
                    Button2.BackColor = Color.Lime
                    Button3.BackColor = Color.Lime
                    Button4.BackColor = Color.LightGray
                End If
            End If
        End Sub
    
        Dim BGW1Active As Boolean = False
        Dim BGW1Percent As Integer = 0
        Dim BGW1Item As String = ""
    
        Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
            For Each Item In FileInfo
                BGW1Item = Item
                Using zipToOpen As FileStream = New FileStream(ZipFiletoUse, FileMode.Open)
                    Using archive As ZipArchive = New ZipArchive(zipToOpen, ZipArchiveMode.Update)
                        Dim TempSplit() As String
                        TempSplit = Item.Split("\"c)
                        Dim readmeEntry As ZipArchiveEntry = archive.CreateEntry(TempSplit(TempSplit.Count - 1))
                        Dim BlockSizeToRead As Integer = 4096
                        Dim Buffer As Byte() = New Byte(BlockSizeToRead - 1) {}
                        Using writer As Stream = readmeEntry.Open
                            Using Reader As FileStream = File.Open(Item, FileMode.Open)
                                Dim bytesRead As Integer, totalBytesRead As Integer, bytesMe = 0
                                While (InlineAssignHelper(bytesRead, Reader.Read(Buffer, 0, Buffer.Length - 1))) > 0
                                    writer.Write(Buffer, 0, bytesRead)
                                    totalBytesRead += bytesRead
                                    BGW1Percent = CInt(totalBytesRead / FilesToZipSize * 100)
                                End While
                            End Using
                        End Using
                    End Using
                End Using
            Next
            BGW1Active = False
        End Sub
    
        Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
            If BGW1Active = True Then
                ProgressBar1.Value = BGW1Percent
                Label1.Text = "File being zipped is " & BGW1Item
                Label2.Text = "Percent zipped is " & BGW1Percent.ToString & ChrW(37)
            Else
                Timer1.Stop()
                Button1.Enabled = True
                Button2.Enabled = True
                Button3.Enabled = True
                Button1.BackColor = Color.Lime
                Button2.BackColor = Color.Lime
                Button3.BackColor = Color.Lime
                ListView1.Items.Clear()
                Label1.Text = "Waiting"
                Label2.Text = "Waiting"
                ProgressBar1.Value = 0
                FilesToZipSize = 0
                BGW1Percent = 0
                BGW1Item = ""
            End If
    
        End Sub
    
        Dim BGW2Active As Boolean = False
        Dim BGW2Percent As Integer = 0
        Dim BGW2Item As String = ""
    
        Private Sub BackgroundWorker2_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker2.DoWork
            Using archive As ZipArchive = ZipFile.OpenRead(ZipFolderToUnzipFilesFrom)
                For Each Item In CheckedListBox1.CheckedItems
                    For Each entry As ZipArchiveEntry In archive.Entries
                        If entry.FullName.ToString = Item.ToString Then
                            BGW2Item = Item.ToString
                            Using Reader As Stream = entry.Open
                                Using Writer As FileStream = File.Open(Path.Combine(FolderToUnzipFilesTo, Item.ToString), FileMode.OpenOrCreate)
                                    Dim bytesWritten As Integer, totalBytesWritten As Integer, bytesMe = 0
                                    Dim BlockSizeToWrite As Integer = 4096
                                    Dim Buffer As Byte() = New Byte(BlockSizeToWrite - 1) {}
                                    While (InlineAssignHelper(bytesWritten, Reader.Read(Buffer, 0, Buffer.Length - 1))) > 0
                                        Writer.Write(Buffer, 0, bytesWritten)
                                        totalBytesWritten += bytesWritten
                                        BGW2Percent = CInt(totalBytesWritten / FilesToUnzipSize * 100)
                                    End While
                                End Using
                            End Using
                        End If
                    Next
                Next
            End Using
            BGW2Active = False
        End Sub
    
        Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
            If BGW2Active = True Then
                ProgressBar1.Value = BGW2Percent
                Label1.Text = "File being unzipped is " & BGW2Item
                Label2.Text = "Percent unzipped is " & BGW2Percent.ToString & ChrW(37)
            Else
                Timer2.Stop()
                Button1.Enabled = True
                Button2.Enabled = True
                Button3.Enabled = True
                Button1.BackColor = Color.Lime
                Button2.BackColor = Color.Lime
                Button3.BackColor = Color.Lime
                Button4.BackColor = Color.LightGray
                CheckedListBox1.Items.Clear()
                Label1.Text = "Waiting"
                Label2.Text = "Waiting"
                ProgressBar1.Value = 0
                FilesToUnzipSize = 0
                BGW2Percent = 0
                BGW2Item = ""
            End If
        End Sub
    
        Private Function InlineAssignHelper(Of T)(ByRef target As T, value As T) As T
            target = value
            Return value
        End Function
    
    End Class


    Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.


    Thursday, January 23, 2014 8:07 PM

All replies

  • Hello,

       for extraction and compression not provides progress method, If you want progress bar updating,  Gets the total number of bytes that need to be compressed,, compress the files by whatever chunk size that you choose and then report progress at whatever level of detail that you wish.


    -----------------------------------------
     if the reply help you mark it as your answer.
     Free Managed .NET Word Component(Create, Modify, Convert & Print)


    • Proposed as answer by Mr. Monkeyboy Thursday, January 23, 2014 5:11 AM
    Wednesday, January 22, 2014 7:19 AM
  • I suppose you are using the ZipFile Class which is only available in .Net 4.5 (and later above .Net 4.5 I would guess).

    I'm fairly certain that can be done but it will take a while to try it.

    How to: Compress and Extract Files


    Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.

    Wednesday, January 22, 2014 4:45 PM
  • You could use the third-party DotNetZip Library. I haven't used it, but here is a thread asking about using a progress bar: Handle progress-bar.

    HTH,

    Andrew

    Wednesday, January 22, 2014 7:34 PM
  • You'll have to extract each file individually so that you have a chance to update the progress bar.   Keep in mind that the process is likely to occur much faster than the progressbar can actually update unless the archive is very large.

    Here's a brief example of one way to do it:

    'Add references to:
    '  System.IO.Compression
    '  System.IO.Compression.FileSystem
    Imports System.IO
    Imports System.IO.Compression
    
    Public Class Form1
        Friend ProgressBar1 As New ProgressBar
        Friend WithEvents Button1 As New Button With {.Top = ProgressBar1.Height + 4}
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Controls.Add(ProgressBar1)
            Controls.Add(Button1)
        End Sub
    
        Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Button1.Enabled = False
            Await ExtractAllAsync("c:\test\test.zip", "c:\test\test extract", ProgressBar1)
            Button1.Enabled = True
        End Sub
    
        Private Async Function ExtractAllAsync(zipFilePath As String, extractPath As String, progress As ProgressBar) As Task
            Try
                Dim extractCount, skipCount, errorCount As Integer
                Using archive As ZipArchive = ZipFile.OpenRead(zipFilePath)
                    progress.Minimum = 0
                    progress.Maximum = archive.Entries.Count
                    Await Task.Run(Sub()
                                       Dim count As Integer = archive.Entries.Count
                                       For i As Integer = 0 To count - 1
                                           Try
                                               Dim entry As ZipArchiveEntry = archive.Entries(i)
                                               entry.ExtractToFile(Path.Combine(extractPath, entry.FullName))
                                               extractCount += 1
                                           Catch ioex As IOException
                                               If ioex.Message.EndsWith("already exists.") Then
                                                   skipCount += 1
                                               Else
                                                   errorCount += 1
                                               End If
                                           Catch ex As Exception
                                               errorCount += 1
                                           End Try
                                           Invoke(Sub() progress.Value += 1)
                                           'System.Threading.Thread.Sleep(100) 'might want delay to see progress animation better
                                       Next
                                       'System.Threading.Thread.Sleep(100)
                                   End Sub)
                End Using
                MessageBox.Show(String.Format("Extracted {0} files, skipping {1} because they exist, with {2} errors.", extractCount, skipCount, errorCount), "Extraction Complete", MessageBoxButtons.OK, MessageBoxIcon.Information)
                progress.Value = 0
            Catch ex As Exception
                MessageBox.Show(ex.Message, "Error Opening Zip File", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End Try
        End Function
    End Class


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"


    Wednesday, January 22, 2014 8:10 PM
    Moderator
  • @Mr.Monkeyboy

    You should not post an example if you can't make it work without turning off cross-thread checking.  That property exists solely for the VB6 upgrade wizard and should never be set on purpose.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"


    Thursday, January 23, 2014 5:43 PM
    Moderator
  • @Mr.Monkeyboy

    You should not post an example if you can't make it work without turning off cross-thread checking.  That property exists solely for the VB6 upgrade wizard and should never be set on purpose.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"



    O.K.

    Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.

    Thursday, January 23, 2014 5:53 PM
  • @Mr.Monkeyboy

    You should not post an example if you can't make it work without turning off cross-thread checking.  That property exists solely for the VB6 upgrade wizard and should never be set on purpose.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"



    O.K.

    Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.

    Thank you.

    To correct your sample, look inside of your DoWork routine(s) and anywhere you need to access a control member, either do so through ReportProgress or create a delegate method to do that work and Invoke the delegate.  It is often easiest to use the generic ones like Me.Invoke(New Action(AddressOf mywork))

    I'd be happy to help you understand the Action and Func delegates more if you'd like to start a thread on it.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Thursday, January 23, 2014 6:02 PM
    Moderator
  • Well I changed it by using some timers.

    Although it seems to me that backgroundworkers are passing variables that were created in another thread information without crossthread issues. So I'm not sure why a background worker can pass a variable information but not a control information without a crossthread issue.

    This code is pretty much in line with what Noodles LV proposed.

    I'll post some images a bit later.

    Option Strict On
    
    ' NOTE: Only works with .Net 4.5 or above. Compile to .Net 4.5 or above.
    ' Also crashes if you attempt to zip a shortcut.
    
    Imports System.IO
    Imports System.IO.Compression ' Add reference to this in Assemblies as well as a reference to System.IO.Compression.FileSystem I think.
    
    Public Class Form1
    
        ' How to: Compress and Extract Files http://msdn.microsoft.com/en-us/library/ms404280(v=vs.110).aspx
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.CenterToScreen()
            Me.BackColor = Color.PapayaWhip
            Me.Text = "Zip and Unzip files using .Net 4.5 System.IO.Compression"
            Button1.BackColor = Color.Lime
            Button2.BackColor = Color.Lime
            Button3.BackColor = Color.Lime
            Button4.BackColor = Color.LightGray
            Button4.Enabled = False
            ProgressBar1.Minimum = 0
            ProgressBar1.Maximum = 100
            Label1.Text = "Waiting"
            Label2.Text = "Waiting"
            ListView1.MultiSelect = False
            ListView1.GridLines = True
            ListView1.LabelEdit = True
            ListView1.UseCompatibleStateImageBehavior = False
            ListView1.View = View.Details
            ListView1.Sorting = SortOrder.Ascending
            ListView1.Columns.Add("Files to be Zipped", 434, HorizontalAlignment.Left)
            Timer1.Interval = 1
            Timer2.Interval = 1
        End Sub
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Button1.Enabled = False
            Button2.Enabled = False
            Button3.Enabled = False
            Button1.BackColor = Color.OrangeRed
            Button2.BackColor = Color.LightGray
            Button3.BackColor = Color.LightGray
            Dim SFD As New SaveFileDialog
            SFD.Title = "Create Zip file. Type in name (i.e. ZipFile), do not add .Zip extension."
            SFD.InitialDirectory = "C:\Users\John\Desktop"
            SFD.DefaultExt = ""
            SFD.Filter = "Zip Files (*.Zip)|*.Zip"
            If SFD.ShowDialog = Windows.Forms.DialogResult.OK Then
                My.Computer.FileSystem.CreateDirectory(SFD.FileName.ToString.Replace(".Zip", ""))
                ZipFile.CreateFromDirectory(SFD.FileName.ToString.Replace(".Zip", ""), SFD.FileName)
                If My.Computer.FileSystem.DirectoryExists(SFD.FileName.ToString.Replace(".Zip", "")) Then
                    My.Computer.FileSystem.DeleteDirectory(SFD.FileName.ToString.Replace(".Zip", ""), FileIO.DeleteDirectoryOption.DeleteAllContents)
                End If
            End If
            Button1.Enabled = True
            Button2.Enabled = True
            Button3.Enabled = True
            Button1.BackColor = Color.Lime
            Button2.BackColor = Color.Lime
            Button3.BackColor = Color.Lime
        End Sub
    
    
        Dim FilesToZipSize As Integer = 0
        Dim FileInfo() As String
        Dim ZipFiletoUse As String = ""
    
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            Button1.Enabled = False
            Button2.Enabled = False
            Button3.Enabled = False
            Button1.BackColor = Color.LightGray
            Button2.BackColor = Color.OrangeRed
            Button3.BackColor = Color.LightGray
    
            Dim OFD1 As New OpenFileDialog
            OFD1.Title = "Select Zip file to use"
            OFD1.InitialDirectory = "C:\Users\John\Desktop"
            OFD1.Filter = "Zip Files (*.Zip)|*.Zip"
            OFD1.Multiselect = False
    
            Dim OFD2 As New OpenFileDialog
            OFD2.Title = "Select files to Zip"
            OFD2.Multiselect = True
            OFD2.InitialDirectory = "C:\Users\John\Desktop"
            OFD2.Filter = "All Files|*.*"
    
            If OFD1.ShowDialog = Windows.Forms.DialogResult.OK Then
                ZipFileToUse = OFD1.FileName
                If OFD2.ShowDialog = Windows.Forms.DialogResult.OK Then
                    For Each Item In OFD2.FileNames
                        FilesToZipSize += CInt(FileLen(Item))
                        ListView1.Items.Add(Item)
                    Next
                    FileInfo = OFD2.FileNames
                    BGW1Active = True
                    Timer1.Start()
                    ProgressBar1.Value = 0
                    BackgroundWorker1.RunWorkerAsync()
                End If
            End If
        End Sub
    
        Dim ZipFolderToUnzipFilesFrom As String = ""
    
        Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
            Button1.Enabled = False
            Button2.Enabled = False
            Button3.Enabled = False
            Button1.BackColor = Color.LightGray
            Button2.BackColor = Color.LightGray
            Button3.BackColor = Color.OrangeRed
            CheckedListBox1.Items.Clear()
            Dim OFD As New OpenFileDialog
            OFD.Title = "Select Zip folder to use"
            OFD.InitialDirectory = "C:\Users\John\Desktop"
            OFD.Filter = "Zip Files (*.Zip)|*.Zip"
            OFD.Multiselect = False
            If OFD.ShowDialog = Windows.Forms.DialogResult.OK Then
                ZipFolderToUnzipFilesFrom = OFD.FileName
                Using archive As ZipArchive = ZipFile.OpenRead(OFD.FileName)
                    For Each entry As ZipArchiveEntry In archive.Entries
                        CheckedListBox1.Items.Add(entry.ToString)
                    Next
                End Using
                If CheckedListBox1.Items.Count = 0 Then
                    Button1.Enabled = True
                    Button2.Enabled = True
                    Button3.Enabled = True
                    Button1.BackColor = Color.Lime
                    Button2.BackColor = Color.Lime
                    Button3.BackColor = Color.Lime
                End If
            End If
    
        End Sub
    
        Private Sub CheckedListBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles CheckedListBox1.SelectedIndexChanged
            If CheckedListBox1.CheckedItems.Count > 0 Then
                Button4.Enabled = True
                Button4.BackColor = Color.Lime
            End If
        End Sub
    
        Dim FolderToUnzipFilesTo As String = ""
        Dim FilesToUnzipSize As Integer = 0
    
        Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
            Button3.BackColor = Color.LightGray
            If CheckedListBox1.CheckedItems.Count = 0 Then
                Button1.Enabled = True
                Button2.Enabled = True
                Button3.Enabled = True
                Button1.BackColor = Color.Lime
                Button2.BackColor = Color.Lime
            Else
                Button4.Enabled = False
                Button4.BackColor = Color.OrangeRed
                Dim FBD As New FolderBrowserDialog
                FBD.Description = "Select folder or create folder to unzip file(s) to"
                FBD.RootFolder = Environment.SpecialFolder.Desktop
                If FBD.ShowDialog = Windows.Forms.DialogResult.OK Then
                    FolderToUnzipFilesTo = FBD.SelectedPath
                    Using archive As ZipArchive = ZipFile.OpenRead(ZipFolderToUnzipFilesFrom)
                        For Each Item In CheckedListBox1.CheckedItems
                            For Each entry As ZipArchiveEntry In archive.Entries
                                If entry.FullName.ToString = Item.ToString Then
                                    FilesToUnzipSize += CInt(entry.Length)
                                End If
                            Next
                        Next
                    End Using
                    BGW2Active = True
                    Timer2.Start()
                    ProgressBar1.Value = 0
                    BackgroundWorker2.RunWorkerAsync()
                Else
                    Button1.Enabled = True
                    Button2.Enabled = True
                    Button3.Enabled = True
                    Button1.BackColor = Color.Lime
                    Button2.BackColor = Color.Lime
                    Button3.BackColor = Color.Lime
                    Button4.BackColor = Color.LightGray
                End If
            End If
        End Sub
    
        Dim BGW1Active As Boolean = False
        Dim BGW1Percent As Integer = 0
        Dim BGW1Item As String = ""
    
        Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
            For Each Item In FileInfo
                BGW1Item = Item
                Using zipToOpen As FileStream = New FileStream(ZipFiletoUse, FileMode.Open)
                    Using archive As ZipArchive = New ZipArchive(zipToOpen, ZipArchiveMode.Update)
                        Dim TempSplit() As String
                        TempSplit = Item.Split("\"c)
                        Dim readmeEntry As ZipArchiveEntry = archive.CreateEntry(TempSplit(TempSplit.Count - 1))
                        Dim BlockSizeToRead As Integer = 4096
                        Dim Buffer As Byte() = New Byte(BlockSizeToRead - 1) {}
                        Using writer As Stream = readmeEntry.Open
                            Using Reader As FileStream = File.Open(Item, FileMode.Open)
                                Dim bytesRead As Integer, totalBytesRead As Integer, bytesMe = 0
                                While (InlineAssignHelper(bytesRead, Reader.Read(Buffer, 0, Buffer.Length - 1))) > 0
                                    writer.Write(Buffer, 0, bytesRead)
                                    totalBytesRead += bytesRead
                                    BGW1Percent = CInt(totalBytesRead / FilesToZipSize * 100)
                                End While
                            End Using
                        End Using
                    End Using
                End Using
            Next
            BGW1Active = False
        End Sub
    
        Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
            If BGW1Active = True Then
                ProgressBar1.Value = BGW1Percent
                Label1.Text = "File being zipped is " & BGW1Item
                Label2.Text = "Percent zipped is " & BGW1Percent.ToString & ChrW(37)
            Else
                Timer1.Stop()
                Button1.Enabled = True
                Button2.Enabled = True
                Button3.Enabled = True
                Button1.BackColor = Color.Lime
                Button2.BackColor = Color.Lime
                Button3.BackColor = Color.Lime
                ListView1.Items.Clear()
                Label1.Text = "Waiting"
                Label2.Text = "Waiting"
                ProgressBar1.Value = 0
                FilesToZipSize = 0
                BGW1Percent = 0
                BGW1Item = ""
            End If
    
        End Sub
    
        Dim BGW2Active As Boolean = False
        Dim BGW2Percent As Integer = 0
        Dim BGW2Item As String = ""
    
        Private Sub BackgroundWorker2_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker2.DoWork
            Using archive As ZipArchive = ZipFile.OpenRead(ZipFolderToUnzipFilesFrom)
                For Each Item In CheckedListBox1.CheckedItems
                    For Each entry As ZipArchiveEntry In archive.Entries
                        If entry.FullName.ToString = Item.ToString Then
                            BGW2Item = Item.ToString
                            Using Reader As Stream = entry.Open
                                Using Writer As FileStream = File.Open(Path.Combine(FolderToUnzipFilesTo, Item.ToString), FileMode.OpenOrCreate)
                                    Dim bytesWritten As Integer, totalBytesWritten As Integer, bytesMe = 0
                                    Dim BlockSizeToWrite As Integer = 4096
                                    Dim Buffer As Byte() = New Byte(BlockSizeToWrite - 1) {}
                                    While (InlineAssignHelper(bytesWritten, Reader.Read(Buffer, 0, Buffer.Length - 1))) > 0
                                        Writer.Write(Buffer, 0, bytesWritten)
                                        totalBytesWritten += bytesWritten
                                        BGW2Percent = CInt(totalBytesWritten / FilesToUnzipSize * 100)
                                    End While
                                End Using
                            End Using
                        End If
                    Next
                Next
            End Using
            BGW2Active = False
        End Sub
    
        Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
            If BGW2Active = True Then
                ProgressBar1.Value = BGW2Percent
                Label1.Text = "File being unzipped is " & BGW2Item
                Label2.Text = "Percent unzipped is " & BGW2Percent.ToString & ChrW(37)
            Else
                Timer2.Stop()
                Button1.Enabled = True
                Button2.Enabled = True
                Button3.Enabled = True
                Button1.BackColor = Color.Lime
                Button2.BackColor = Color.Lime
                Button3.BackColor = Color.Lime
                Button4.BackColor = Color.LightGray
                CheckedListBox1.Items.Clear()
                Label1.Text = "Waiting"
                Label2.Text = "Waiting"
                ProgressBar1.Value = 0
                FilesToUnzipSize = 0
                BGW2Percent = 0
                BGW2Item = ""
            End If
        End Sub
    
        Private Function InlineAssignHelper(Of T)(ByRef target As T, value As T) As T
            target = value
            Return value
        End Function
    
    End Class


    Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.


    Thursday, January 23, 2014 8:07 PM
  • You can pass variables between threads, so long as the object that the variable represents is not owned by a particular thread.  When a control instance is created, it is owned by the thread that created it and cannot (should not) be directly access by another thread.  If the variable is accessible from more than one thread, then you have to code carefully to avoid race conditions and deadlocks.  You also have to be careful that you don't inadvertently reduce performance instead of increasing it.

    The BackgroundWorker made things easier if you put all of the secondary thread operations in DoWork and only interact with the primary thread through ReportProgress.

    But even the BackgroundWorker has been replaced in favor of using Await in VS2012+.  I was a little late to adopt it because I hated 2012 lol but I'm in 2013 now and getting comfortable and getting used to Await has been at the top of my to-do list.  It really does make async and multithreaded code much cleaner to write and read/debug.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Thursday, January 23, 2014 8:59 PM
    Moderator
  • I saw Await in your example you posted but as I'm unfamiliar with it I did not want to try it with all the other issues I was having just to get the code I posted to work. In fact Async code is not in my scope of knowledge at this moment in time. And probably not soon either.

    Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.


    • Edited by Mr. Monkeyboy Thursday, January 23, 2014 9:10 PM 5555
    Thursday, January 23, 2014 9:07 PM
  • Images of example working.


    Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.

    Friday, January 24, 2014 11:03 PM
  • Look here:

    http://dotnetzip.codeplex.com/downloads/get/258014

    and here

    http://archive.msdn.microsoft.com/DotNetZip/Release/ProjectReleases.aspx?ReleaseId=3097

    has everything you asked about

    Sunday, January 26, 2014 5:31 AM