使用带有进度报告的C#提取ZipFile

使用带有进度报告的C#提取ZipFile,c#,winforms,C#,Winforms,有人能告诉我,是否有可能(并给出一个例子,如果有),如何让进度条(和状态标签,如果可能的话)显示正在使用“ZipFile”(Ionic.ZIP,)提取的ZIP文件的进度 我的WinForm在将ZIP文件从我选择的路径提取到一个新路径方面做得很好,使用文本框和浏览按钮以及所有的jazz都不用担心。。。然而,唯一的问题是,在这段时间里,我不能在我的表单上使用任何东西,就好像它已经冻结了一样,但这只是因为它在后台解压了ZIP文件 ZIP文件是一个很大的文件,我想通过添加一个进度条来显示解压是如何进行的

有人能告诉我,是否有可能(并给出一个例子,如果有),如何让进度条(和状态标签,如果可能的话)显示正在使用“ZipFile”(Ionic.ZIP,)提取的ZIP文件的进度

我的WinForm在将ZIP文件从我选择的路径提取到一个新路径方面做得很好,使用文本框和浏览按钮以及所有的jazz都不用担心。。。然而,唯一的问题是,在这段时间里,我不能在我的表单上使用任何东西,就好像它已经冻结了一样,但这只是因为它在后台解压了ZIP文件

ZIP文件是一个很大的文件,我想通过添加一个进度条来显示解压是如何进行的,并且有一个准确的ETA,从而减少对正在发生的事情的混淆

当然这是可能的,我只是不知道如何在C#WinForms中实现这一点,我已经在网络上进行了相当不错的浏览,但没有真正找到适合我的示例

下面是一个粗略的例子:

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 > 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);

            } 
        }
    }
}
更新(2014年11月4日):我已经删除了文本框,现在回到简单的基础,下面的工作与背景工人,但取消按钮没有对RAR文件的影响。。。有什么建议吗

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
    {
        /// <summary>
        /// The backgroundworker object on which the time consuming operation 
        /// shall be executed
        /// </summary>
        BackgroundWorker backgroundWorker1;

        public Form1()
        {
            InitializeComponent();
            backgroundWorker1 = new BackgroundWorker();

            // Create a background worker thread that ReportsProgress &
            // 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;
        }

        /// <summary>
        /// On completed do the appropriate task
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        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;
        }

        /// <summary>
        /// Notification is performed here to the progress bar
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        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() + "%";
        }

        /// <summary>
        /// Time consuming operations go here </br>
        /// i.e. Database operations,Reporting
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        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 < 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();
            }
        }
    }
} 
使用系统;
使用System.Collections.Generic;
使用系统组件模型;
使用系统数据;
使用系统图;
使用系统线程;
使用系统文本;
使用System.Windows.Forms;
使用Ionic.Zip;
使用System.IO;
命名空间BackgroundWorkerSample
{
//BackgroundWorker将用于执行长时间运行的操作
//在后台线程上。这允许用户界面自由绘制
//以及用户可能要执行的其他操作。后台
//线程将使用ReportProgress事件更新ProgressBar
//在UI线程上。
公共部分类Form1:Form
{
/// 
///对其执行耗时操作的backgroundworker对象
///执行
/// 
背景工人背景工人1;
公共表格1()
{
初始化组件();
backgroundWorker1=新的BackgroundWorker();
//创建报告进程的后台工作线程&
//支撑扫描细胞
//连接适当的事件。
backgroundWorker1.DoWork+=新的DoWorkerVenthandler(backgroundWorker1_DoWork);
backgroundWorker1.ProgressChanged+=新的ProgressChangedEventHandler
(背景工作1_进度变更);
backgroundWorker1.RunWorkerCompleted+=新的RunWorkerCompletedEventHandler
(后台工作1_运行工作完成);
backgroundWorker1.WorkerReportsProgress=true;
backgroundWorker1.WorkerSupportsScanCellation=true;
}
/// 
///完成后,执行适当的任务
/// 
/// 
/// 
void backgroundWorker1\u RunWorkerCompleted(对象发送方,runworkercompletedeventarge)
{
//后台程序已经完成,我们需要检查
//我们的响应是查看是否发生了错误,取消了
//请求或如果我们成功完成。
如果(如已取消)
{
lblStatus.Text=“任务已取消。”;
}
//检查后台进程中是否发生错误。
否则如果(例如错误!=null)
{
lblStatus.Text=“执行后台操作时出错。”;
}
其他的
{
//一切正常完成。
lblStatus.Text=“任务已完成…”;
}
//相应地更改UI上按钮的状态
btnStart.Enabled=true;
btnCancel.Enabled=false;
}
/// 
///在此处向进度条执行通知
/// 
/// 
/// 
void backgroundWorker1\u ProgressChanged(对象发送方,ProgressChangedEventArgs e)
{
//此函数在UI线程上激发,因此可以安全地进行编辑
//直接使用UI控件,与控件没有任何有趣的业务。调用:)
//使用从提供给我们的整数更新progressBar
//ReportProgress()函数。
progressBar1.值=e.ProgressPercentage;
lblStatus.Text=“处理……”+progressBar1.Value.ToString()+“%”;
}
/// 
///耗时的操作在这里进行
///即数据库操作、报告 /// /// /// 无效backgroundWorker1\u DoWork(对象发送方,DoWorkerVentargs e) { //发送方是我们需要的BackgroundWorker对象 //报告进度并检查取消情况。 //注意:永远不要在这里玩UI线程。。。 对于(int i=0;i<100;i++) { //睡眠(100); string INSTALL\u FOLDER=“C:”+@“\”+”程序文件(x86)”+@“\”+”机器人91111“+@“\”+”基本“+@“\”+”字符串“+@“\”+”特殊.rar”; string BURGOS_FOLDER=“C:”++“\”+“程序文件(x86)”++“\”+“机器人91111”++“\”+“BURGOS_文件夹”; 如果(!Directory.Exists(BURGOS_文件夹)) { CreateDirectory(BURGOS_文件夹); 使用(ZipFile zip=ZipFile.Read(安装文件夹)) { ExtractAll(BURGOS_文件夹,ExtractExistingFileAction.OverwriteSilently); } } //定期向主线程报告进度,以便它能够 //更新用户界面。在大多数情况下,您只需发送 //将更新进度条的整数 幕后工作者
/*...*/
using (ZipFile zip = ZipFile.Read(ROBOT_INSTALL_SPECIAL))
        {
            zip.ExtractProgress += 
               new EventHandler<ExtractProgressEventArgs>(zip_ExtractProgress);
            zip.ExtractAll(ROBOT0007, ExtractExistingFileAction.OverwriteSilently);

        }
/*...*/

void zip_ExtractProgress(object sender, ExtractProgressEventArgs e)
{
   if (e.TotalBytesToTransfer > 0)
   {
      progressBar1.Value = Convert.ToInt32(100 * e.BytesTransferred / e.TotalBytesToTransfer);
   }
}
private int totalFiles;
private int filesExtracted;

/*...*/

using (ZipFile zip = ZipFile.Read(ROBOT_INSTALL_SPECIAL))
{
    totalFiles = zip.Count;
    filesExtracted = 0;
    zip.ExtractProgress += ZipExtractProgress; 
    zip.ExtractAll(ROBOT0007, ExtractExistingFileAction.OverwriteSilently);
}

/*...*/

private void ZipExtractProgress(object sender, ExtractProgressEventArgs e)
{
    if (e.EventType != ZipProgressEventType.Extracting_BeforeExtractEntry)
        return;
    filesExtracted++;
    progressBar.Value = 100 * filesExtracted / totalFiles;
}
using System.IO.Compression; private async void Unzip(string filePath) { var _downloadPath = configuration.GetValue("DownloadPath"); var _extractPath = configuration.GetValue("ExtractPath"); var _extractPattern = configuration.GetValue("ExtractPattern"); Console.WriteLine($"Удаление старых файлов из директории: '{_extractPath}'"); var directoryInfo = new DirectoryInfo(_extractPath); foreach (var file in directoryInfo.GetFiles()) { file.Delete(); } Console.WriteLine($"Распаковка файла: '{filePath}'"); var regex = new Regex(_extractPattern); var fileList = new List(); var totalFiles = 0; var filesExtracted = 0; using (var archive = await Task.Run(() => ZipFile.OpenRead(filePath))) { foreach (var file in archive.Entries) { if (regex.IsMatch(file.Name)) { fileList.Add(file); totalFiles++; } } foreach (var file in fileList) { Console.WriteLine($"Извлечение файла: '{file.Name}'"); await Task.Run(() => { file.ExtractToFile($"{_extractPath}{file.Name}"); filesExtracted++; var progress = Convert.ToInt32(100 * filesExtracted / totalFiles); Console.WriteLine($"Извлечено: {progress}%"); }); } } } appsettings.json example { "DownloadPath": "f:\\download\\", "ExtractPath": "f:\\download\\extract\\", "ExtractPattern": "ACTSTAT.DBF|CENTERST.DBF|CURENTST.DBF|ESTSTAT.DBF|FLATTYPE.DBF|NDOCTYPE.DBF|OPERSTAT.DBF|ROOMTYPE.DBF|SOCRBASE.DBF|STRSTAT.DBF|[A-Z]{1}16.DBF", }