title: Extract ZipFile Using C# With Progress Report
body: <p>Can anyone tell me if it is possible(and give an example if it is) on how to have a progress bar(and status label if possible) showing the progress of a ZIP file being extracted using "ZipFile"(Ionic.zip, <a href="http://dotnetzip.codeplex.com/" rel="nofollow">http://dotnetzip.codeplex.com/</a>)?</p>
  
  <p>My WinForm does a great job at extracting a ZIP file from my chosen path to a new path no worries at all using textboxes and browse buttons and all that jazz... However the only issue is i cannot use anything on my form during this time it is as if it has frozen, but its only because its unzipping the ZIP file in the background.</p>
  
  <p>The ZIP file is a big file and i would like to make it less confusing on what is going on by adding and having a progress bar showing how the unzipping is going with a accurate ETA.</p>
  
  <p>Surely this is possible, i just cannot work out how to do it in C# WinForms, i have had a fairly decent look all around the net without really being able to come across a example i can find suitable for me.</p>
  
  <p>Here is a rough example of what i have:</p>
  
  <pre><code>private void button1_Click(object sender, EventArgs e)
  {
      var ROBOT0007 = textBox1.Text + @"\" + "ROBOT0007"; //ROBOT0007 folder
      var ROBOT_INSTALL = textBox1.Text + @"\" + "911" + @"\" + "files"; //ROBOT0007/911/files
      var ROBOT_INSTALL_SPECIAL = ROBOT_INSTALL + @"\" + "special.rar";  //ROBOT0007/911/files/special.rar
  
      //If the path has text...
      if (textBox1.TextLength &gt; 0)
      {
          //if the subfolder doesn't exist then make it.
          if (!Directory.Exists(ROBOT0007))
          {
              Directory.CreateDirectory(ROBOT0007);
          }
  
          //if the textbox directory exists
          if (Directory.Exists(ROBOT0007))
          {
              using (ZipFile zip = ZipFile.Read(ROBOT_INSTALL_SPECIAL))
              {
                  zip.ExtractAll(ROBOT0007, ExtractExistingFileAction.OverwriteSilently);
  
              } 
          }
      }
  }
  </code></pre>
  
  <p>UPDATE(04/11/2014): I have removed the textbox for now gone back to simple basics, the following works with a background worker, however the cancel button has no effect on RAR files... any advice? </p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Data;
  using System.Drawing;
  using System.Threading;
  using System.Text;
  using System.Windows.Forms;
  using Ionic.Zip;
  using System.IO;
  
  namespace BackgroundWorkerSample
  {
      // The BackgroundWorker will be used to perform a long running action
      // on a background thread.  This allows the UI to be free for painting
      // as well as other actions the user may want to perform.  The background
      // thread will use the ReportProgress event to update the ProgressBar
      // on the UI thread.
      public partial class Form1 : Form
      {
          /// &lt;summary&gt;
          /// The backgroundworker object on which the time consuming operation 
          /// shall be executed
          /// &lt;/summary&gt;
          BackgroundWorker backgroundWorker1;
  
          public Form1()
          {
              InitializeComponent();
              backgroundWorker1 = new BackgroundWorker();
  
              // Create a background worker thread that ReportsProgress &amp;
              // SupportsCancellation
              // Hook up the appropriate events.
              backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
              backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler
                      (backgroundWorker1_ProgressChanged);
              backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler
                      (backgroundWorker1_RunWorkerCompleted);
              backgroundWorker1.WorkerReportsProgress = true;
              backgroundWorker1.WorkerSupportsCancellation = true;
          }
  
          /// &lt;summary&gt;
          /// On completed do the appropriate task
          /// &lt;/summary&gt;
          /// &lt;param name="sender"&gt;&lt;/param&gt;
          /// &lt;param name="e"&gt;&lt;/param&gt;
          void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
          {
              // The background process is complete. We need to inspect
              // our response to see if an error occurred, a cancel was
              // requested or if we completed successfully.  
              if (e.Cancelled)
              {
                  lblStatus.Text = "Task Cancelled.";
              }
  
              // Check to see if an error occurred in the background process.
  
              else if (e.Error != null)
              {
                  lblStatus.Text = "Error while performing background operation.";
              }
              else
              {
                  // Everything completed normally.
                  lblStatus.Text = "Task Completed...";
              }
  
              //Change the status of the buttons on the UI accordingly
              btnStart.Enabled = true;
              btnCancel.Enabled = false;
          }
  
          /// &lt;summary&gt;
          /// Notification is performed here to the progress bar
          /// &lt;/summary&gt;
          /// &lt;param name="sender"&gt;&lt;/param&gt;
          /// &lt;param name="e"&gt;&lt;/param&gt;
          void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
          {
  
              // This function fires on the UI thread so it's safe to edit
  
              // the UI control directly, no funny business with Control.Invoke :)
  
              // Update the progressBar with the integer supplied to us from the
  
              // ReportProgress() function.  
  
              progressBar1.Value = e.ProgressPercentage;
              lblStatus.Text = "Processing......" + progressBar1.Value.ToString() + "%";
          }
  
          /// &lt;summary&gt;
          /// Time consuming operations go here &lt;/br&gt;
          /// i.e. Database operations,Reporting
          /// &lt;/summary&gt;
          /// &lt;param name="sender"&gt;&lt;/param&gt;
          /// &lt;param name="e"&gt;&lt;/param&gt;
          void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
          {
              // The sender is the BackgroundWorker object we need it to
              // report progress and check for cancellation.
              //NOTE : Never play with the UI thread here...
              for (int i = 0; i &lt; 100; i++)
              {
                  //Thread.Sleep(100);
                  string INSTALL_FOLDER= "C:" + @"\" + "Program Files (x86)" + @"\" + "Robot91111"+ @"\" + "basic" + @"\" + "string" + @"\" + "special.rar";
                  string BURGOS_FOLDER = "C:" + @"\" + "Program Files (x86)" + @"\" + "Robot91111" + @"\" + "Burgos_Folder";
                  if (!Directory.Exists(BURGOS_FOLDER))
                      {
                          Directory.CreateDirectory(BURGOS_FOLDER);
                          using (ZipFile zip = ZipFile.Read(INSTALL_FOLDER))
                          {
                              zip.ExtractAll(BURGOS_FOLDER, ExtractExistingFileAction.OverwriteSilently);
                          }
                      }
  
                  // Periodically report progress to the main thread so that it can
                  // update the UI.  In most cases you'll just need to send an
                  // integer that will update a ProgressBar                    
                  backgroundWorker1.ReportProgress(i);
                  // Periodically check if a cancellation request is pending.
                  // If the user clicks cancel the line
                  // m_AsyncWorker.CancelAsync(); if ran above.  This
                  // sets the CancellationPending to true.
                  // You must check this flag in here and react to it.
                  // We react to it by setting e.Cancel to true and leaving
                  if (backgroundWorker1.CancellationPending)
                  {
                      // Set the e.Cancel flag so that the WorkerCompleted event
                      // knows that the process was cancelled.
                      e.Cancel = true;
                      backgroundWorker1.ReportProgress(0);
                      return;
                  }
              }
  
              //Report 100% completion on operation completed
              backgroundWorker1.ReportProgress(100);
          }
  
          private void btnStartAsyncOperation_Click(object sender, EventArgs e)
          {
              //Change the status of the buttons on the UI accordingly
              //The start button is disabled as soon as the background operation is started
              //The Cancel button is enabled so that the user can stop the operation 
              //at any point of time during the execution
              btnStart.Enabled = false;
              btnCancel.Enabled = true;
  
              // Kickoff the worker thread to begin it's DoWork function.
              backgroundWorker1.RunWorkerAsync();
          }
  
          private void btnCancel_Click(object sender, EventArgs e)
          {
              if (backgroundWorker1.IsBusy)
              {
  
                  // Notify the worker thread that a cancel has been requested.
  
                  // The cancel will not actually happen until the thread in the
  
                  // DoWork checks the backgroundWorker1.CancellationPending flag. 
  
                  backgroundWorker1.CancelAsync();
              }
          }
      }
  } 
  </code></pre>