// ZipFile.Events.cs // ------------------------------------------------------------------ // // Copyright (c) 2008, 2009, 2011 Dino Chiesa . // All rights reserved. // // This code module is part of DotNetZip, a zipfile class library. // // ------------------------------------------------------------------ // // This code is licensed under the Microsoft Public License. // See the file License.txt for the license details. // More info on: http://dotnetzip.codeplex.com // // ------------------------------------------------------------------ // // last saved (in emacs): // Time-stamp: <2011-July-09 08:42:35> // // ------------------------------------------------------------------ // // This module defines the methods for issuing events from the ZipFile class. // // ------------------------------------------------------------------ // using System; using System.IO; namespace OfficeOpenXml.Packaging.Ionic.Zip { internal partial class ZipFile { private string ArchiveNameForEvent { get { return (_name != null) ? _name : "(stream)"; } } #region Save /// /// An event handler invoked when a Save() starts, before and after each /// entry has been written to the archive, when a Save() completes, and /// during other Save events. /// /// /// /// /// Depending on the particular event, different properties on the parameter are set. The following /// table summarizes the available EventTypes and the conditions under /// which this event handler is invoked with a /// SaveProgressEventArgs with the given EventType. /// /// /// /// /// value of EntryType /// Meaning and conditions /// /// /// /// ZipProgressEventType.Saving_Started /// Fired when ZipFile.Save() begins. /// /// /// /// /// ZipProgressEventType.Saving_BeforeSaveEntry /// /// Fired within ZipFile.Save(), just before writing data for each /// particular entry. /// /// /// /// /// ZipProgressEventType.Saving_AfterSaveEntry /// /// Fired within ZipFile.Save(), just after having finished writing data /// for each particular entry. /// /// /// /// /// ZipProgressEventType.Saving_Completed /// Fired when ZipFile.Save() has completed. /// /// /// /// /// ZipProgressEventType.Saving_AfterSaveTempArchive /// /// Fired after the temporary file has been created. This happens only /// when saving to a disk file. This event will not be invoked when /// saving to a stream. /// /// /// /// /// ZipProgressEventType.Saving_BeforeRenameTempArchive /// /// Fired just before renaming the temporary file to the permanent /// location. This happens only when saving to a disk file. This event /// will not be invoked when saving to a stream. /// /// /// /// /// ZipProgressEventType.Saving_AfterRenameTempArchive /// /// Fired just after renaming the temporary file to the permanent /// location. This happens only when saving to a disk file. This event /// will not be invoked when saving to a stream. /// /// /// /// /// ZipProgressEventType.Saving_AfterCompileSelfExtractor /// /// Fired after a self-extracting archive has finished compiling. This /// EventType is used only within SaveSelfExtractor(). /// /// /// /// /// ZipProgressEventType.Saving_BytesRead /// /// Set during the save of a particular entry, to update progress of the /// Save(). When this EventType is set, the BytesTransferred is the /// number of bytes that have been read from the source stream. The /// TotalBytesToTransfer is the number of bytes in the uncompressed /// file. /// /// /// /// /// /// /// /// /// This example uses an anonymous method to handle the /// SaveProgress event, by updating a progress bar. /// /// /// progressBar1.Value = 0; /// progressBar1.Max = listbox1.Items.Count; /// using (ZipFile zip = new ZipFile()) /// { /// // listbox1 contains a list of filenames /// zip.AddFiles(listbox1.Items); /// /// // do the progress bar: /// zip.SaveProgress += (sender, e) => { /// if (e.EventType == ZipProgressEventType.Saving_BeforeWriteEntry) { /// progressBar1.PerformStep(); /// } /// }; /// /// zip.Save(fs); /// } /// /// /// /// /// This example uses a named method as the /// SaveProgress event handler, to update the user, in a /// console-based application. /// /// /// static bool justHadByteUpdate= false; /// public static void SaveProgress(object sender, SaveProgressEventArgs e) /// { /// if (e.EventType == ZipProgressEventType.Saving_Started) /// Console.WriteLine("Saving: {0}", e.ArchiveName); /// /// else if (e.EventType == ZipProgressEventType.Saving_Completed) /// { /// justHadByteUpdate= false; /// Console.WriteLine(); /// Console.WriteLine("Done: {0}", e.ArchiveName); /// } /// /// else if (e.EventType == ZipProgressEventType.Saving_BeforeWriteEntry) /// { /// if (justHadByteUpdate) /// Console.WriteLine(); /// Console.WriteLine(" Writing: {0} ({1}/{2})", /// e.CurrentEntry.FileName, e.EntriesSaved, e.EntriesTotal); /// justHadByteUpdate= false; /// } /// /// else if (e.EventType == ZipProgressEventType.Saving_EntryBytesRead) /// { /// if (justHadByteUpdate) /// Console.SetCursorPosition(0, Console.CursorTop); /// Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, e.TotalBytesToTransfer, /// e.BytesTransferred / (0.01 * e.TotalBytesToTransfer )); /// justHadByteUpdate= true; /// } /// } /// /// public static ZipUp(string targetZip, string directory) /// { /// using (var zip = new ZipFile()) { /// zip.SaveProgress += SaveProgress; /// zip.AddDirectory(directory); /// zip.Save(targetZip); /// } /// } /// /// /// /// /// Public Sub ZipUp(ByVal targetZip As String, ByVal directory As String) /// Using zip As ZipFile = New ZipFile /// AddHandler zip.SaveProgress, AddressOf MySaveProgress /// zip.AddDirectory(directory) /// zip.Save(targetZip) /// End Using /// End Sub /// /// Private Shared justHadByteUpdate As Boolean = False /// /// Public Shared Sub MySaveProgress(ByVal sender As Object, ByVal e As SaveProgressEventArgs) /// If (e.EventType Is ZipProgressEventType.Saving_Started) Then /// Console.WriteLine("Saving: {0}", e.ArchiveName) /// /// ElseIf (e.EventType Is ZipProgressEventType.Saving_Completed) Then /// justHadByteUpdate = False /// Console.WriteLine /// Console.WriteLine("Done: {0}", e.ArchiveName) /// /// ElseIf (e.EventType Is ZipProgressEventType.Saving_BeforeWriteEntry) Then /// If justHadByteUpdate Then /// Console.WriteLine /// End If /// Console.WriteLine(" Writing: {0} ({1}/{2})", e.CurrentEntry.FileName, e.EntriesSaved, e.EntriesTotal) /// justHadByteUpdate = False /// /// ElseIf (e.EventType Is ZipProgressEventType.Saving_EntryBytesRead) Then /// If justHadByteUpdate Then /// Console.SetCursorPosition(0, Console.CursorTop) /// End If /// Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, _ /// e.TotalBytesToTransfer, _ /// (CDbl(e.BytesTransferred) / (0.01 * e.TotalBytesToTransfer))) /// justHadByteUpdate = True /// End If /// End Sub /// /// /// /// /// /// This is a more complete example of using the SaveProgress /// events in a Windows Forms application, with a /// Thread object. /// /// /// delegate void SaveEntryProgress(SaveProgressEventArgs e); /// delegate void ButtonClick(object sender, EventArgs e); /// /// internal class WorkerOptions /// { /// public string ZipName; /// public string Folder; /// public string Encoding; /// public string Comment; /// public int ZipFlavor; /// public Zip64Option Zip64; /// } /// /// private int _progress2MaxFactor; /// private bool _saveCanceled; /// private long _totalBytesBeforeCompress; /// private long _totalBytesAfterCompress; /// private Thread _workerThread; /// /// /// private void btnZipup_Click(object sender, EventArgs e) /// { /// KickoffZipup(); /// } /// /// private void btnCancel_Click(object sender, EventArgs e) /// { /// if (this.lblStatus.InvokeRequired) /// { /// this.lblStatus.Invoke(new ButtonClick(this.btnCancel_Click), new object[] { sender, e }); /// } /// else /// { /// _saveCanceled = true; /// lblStatus.Text = "Canceled..."; /// ResetState(); /// } /// } /// /// private void KickoffZipup() /// { /// _folderName = tbDirName.Text; /// /// if (_folderName == null || _folderName == "") return; /// if (this.tbZipName.Text == null || this.tbZipName.Text == "") return; /// /// // check for existence of the zip file: /// if (System.IO.File.Exists(this.tbZipName.Text)) /// { /// var dlgResult = MessageBox.Show(String.Format("The file you have specified ({0}) already exists." + /// " Do you want to overwrite this file?", this.tbZipName.Text), /// "Confirmation is Required", MessageBoxButtons.YesNo, MessageBoxIcon.Question); /// if (dlgResult != DialogResult.Yes) return; /// System.IO.File.Delete(this.tbZipName.Text); /// } /// /// _saveCanceled = false; /// _nFilesCompleted = 0; /// _totalBytesAfterCompress = 0; /// _totalBytesBeforeCompress = 0; /// this.btnOk.Enabled = false; /// this.btnOk.Text = "Zipping..."; /// this.btnCancel.Enabled = true; /// lblStatus.Text = "Zipping..."; /// /// var options = new WorkerOptions /// { /// ZipName = this.tbZipName.Text, /// Folder = _folderName, /// Encoding = "ibm437" /// }; /// /// if (this.comboBox1.SelectedIndex != 0) /// { /// options.Encoding = this.comboBox1.SelectedItem.ToString(); /// } /// /// if (this.radioFlavorSfxCmd.Checked) /// options.ZipFlavor = 2; /// else if (this.radioFlavorSfxGui.Checked) /// options.ZipFlavor = 1; /// else options.ZipFlavor = 0; /// /// if (this.radioZip64AsNecessary.Checked) /// options.Zip64 = Zip64Option.AsNecessary; /// else if (this.radioZip64Always.Checked) /// options.Zip64 = Zip64Option.Always; /// else options.Zip64 = Zip64Option.Never; /// /// options.Comment = String.Format("Encoding:{0} || Flavor:{1} || ZIP64:{2}\r\nCreated at {3} || {4}\r\n", /// options.Encoding, /// FlavorToString(options.ZipFlavor), /// options.Zip64.ToString(), /// System.DateTime.Now.ToString("yyyy-MMM-dd HH:mm:ss"), /// this.Text); /// /// if (this.tbComment.Text != TB_COMMENT_NOTE) /// options.Comment += this.tbComment.Text; /// /// _workerThread = new Thread(this.DoSave); /// _workerThread.Name = "Zip Saver thread"; /// _workerThread.Start(options); /// this.Cursor = Cursors.WaitCursor; /// } /// /// /// private void DoSave(Object p) /// { /// WorkerOptions options = p as WorkerOptions; /// try /// { /// using (var zip1 = new ZipFile()) /// { /// zip1.ProvisionalAlternateEncoding = System.Text.Encoding.GetEncoding(options.Encoding); /// zip1.Comment = options.Comment; /// zip1.AddDirectory(options.Folder); /// _entriesToZip = zip1.EntryFileNames.Count; /// SetProgressBars(); /// zip1.SaveProgress += this.zip1_SaveProgress; /// /// zip1.UseZip64WhenSaving = options.Zip64; /// /// if (options.ZipFlavor == 1) /// zip1.SaveSelfExtractor(options.ZipName, SelfExtractorFlavor.WinFormsApplication); /// else if (options.ZipFlavor == 2) /// zip1.SaveSelfExtractor(options.ZipName, SelfExtractorFlavor.ConsoleApplication); /// else /// zip1.Save(options.ZipName); /// } /// } /// catch (System.Exception exc1) /// { /// MessageBox.Show(String.Format("Exception while zipping: {0}", exc1.Message)); /// btnCancel_Click(null, null); /// } /// } /// /// /// /// void zip1_SaveProgress(object sender, SaveProgressEventArgs e) /// { /// switch (e.EventType) /// { /// case ZipProgressEventType.Saving_AfterWriteEntry: /// StepArchiveProgress(e); /// break; /// case ZipProgressEventType.Saving_EntryBytesRead: /// StepEntryProgress(e); /// break; /// case ZipProgressEventType.Saving_Completed: /// SaveCompleted(); /// break; /// case ZipProgressEventType.Saving_AfterSaveTempArchive: /// // this event only occurs when saving an SFX file /// TempArchiveSaved(); /// break; /// } /// if (_saveCanceled) /// e.Cancel = true; /// } /// /// /// /// private void StepArchiveProgress(SaveProgressEventArgs e) /// { /// if (this.progressBar1.InvokeRequired) /// { /// this.progressBar1.Invoke(new SaveEntryProgress(this.StepArchiveProgress), new object[] { e }); /// } /// else /// { /// if (!_saveCanceled) /// { /// _nFilesCompleted++; /// this.progressBar1.PerformStep(); /// _totalBytesAfterCompress += e.CurrentEntry.CompressedSize; /// _totalBytesBeforeCompress += e.CurrentEntry.UncompressedSize; /// /// // reset the progress bar for the entry: /// this.progressBar2.Value = this.progressBar2.Maximum = 1; /// /// this.Update(); /// } /// } /// } /// /// /// private void StepEntryProgress(SaveProgressEventArgs e) /// { /// if (this.progressBar2.InvokeRequired) /// { /// this.progressBar2.Invoke(new SaveEntryProgress(this.StepEntryProgress), new object[] { e }); /// } /// else /// { /// if (!_saveCanceled) /// { /// if (this.progressBar2.Maximum == 1) /// { /// // reset /// Int64 max = e.TotalBytesToTransfer; /// _progress2MaxFactor = 0; /// while (max > System.Int32.MaxValue) /// { /// max /= 2; /// _progress2MaxFactor++; /// } /// this.progressBar2.Maximum = (int)max; /// lblStatus.Text = String.Format("{0} of {1} files...({2})", /// _nFilesCompleted + 1, _entriesToZip, e.CurrentEntry.FileName); /// } /// /// int xferred = e.BytesTransferred >> _progress2MaxFactor; /// /// this.progressBar2.Value = (xferred >= this.progressBar2.Maximum) /// ? this.progressBar2.Maximum /// : xferred; /// /// this.Update(); /// } /// } /// } /// /// private void SaveCompleted() /// { /// if (this.lblStatus.InvokeRequired) /// { /// this.lblStatus.Invoke(new MethodInvoker(this.SaveCompleted)); /// } /// else /// { /// lblStatus.Text = String.Format("Done, Compressed {0} files, {1:N0}% of original.", /// _nFilesCompleted, (100.00 * _totalBytesAfterCompress) / _totalBytesBeforeCompress); /// ResetState(); /// } /// } /// /// private void ResetState() /// { /// this.btnCancel.Enabled = false; /// this.btnOk.Enabled = true; /// this.btnOk.Text = "Zip it!"; /// this.progressBar1.Value = 0; /// this.progressBar2.Value = 0; /// this.Cursor = Cursors.Default; /// if (!_workerThread.IsAlive) /// _workerThread.Join(); /// } /// /// /// /// /// /// /// internal event EventHandler SaveProgress; internal bool OnSaveBlock(ZipEntry entry, Int64 bytesXferred, Int64 totalBytesToXfer) { EventHandler sp = SaveProgress; if (sp != null) { var e = SaveProgressEventArgs.ByteUpdate(ArchiveNameForEvent, entry, bytesXferred, totalBytesToXfer); sp(this, e); if (e.Cancel) _saveOperationCanceled = true; } return _saveOperationCanceled; } private void OnSaveEntry(int current, ZipEntry entry, bool before) { EventHandler sp = SaveProgress; if (sp != null) { var e = new SaveProgressEventArgs(ArchiveNameForEvent, before, _entries.Count, current, entry); sp(this, e); if (e.Cancel) _saveOperationCanceled = true; } } private void OnSaveEvent(ZipProgressEventType eventFlavor) { EventHandler sp = SaveProgress; if (sp != null) { var e = new SaveProgressEventArgs(ArchiveNameForEvent, eventFlavor); sp(this, e); if (e.Cancel) _saveOperationCanceled = true; } } private void OnSaveStarted() { EventHandler sp = SaveProgress; if (sp != null) { var e = SaveProgressEventArgs.Started(ArchiveNameForEvent); sp(this, e); if (e.Cancel) _saveOperationCanceled = true; } } private void OnSaveCompleted() { EventHandler sp = SaveProgress; if (sp != null) { var e = SaveProgressEventArgs.Completed(ArchiveNameForEvent); sp(this, e); } } #endregion #region Read /// /// An event handler invoked before, during, and after the reading of a zip archive. /// /// /// /// /// Depending on the particular event being signaled, different properties on the /// parameter are set. The following table /// summarizes the available EventTypes and the conditions under which this /// event handler is invoked with a ReadProgressEventArgs with the given EventType. /// /// /// /// /// value of EntryType /// Meaning and conditions /// /// /// /// ZipProgressEventType.Reading_Started /// Fired just as ZipFile.Read() begins. Meaningful properties: ArchiveName. /// /// /// /// /// ZipProgressEventType.Reading_Completed /// Fired when ZipFile.Read() has completed. Meaningful properties: ArchiveName. /// /// /// /// /// ZipProgressEventType.Reading_ArchiveBytesRead /// Fired while reading, updates the number of bytes read for the entire archive. /// Meaningful properties: ArchiveName, CurrentEntry, BytesTransferred, TotalBytesToTransfer. /// /// /// /// /// ZipProgressEventType.Reading_BeforeReadEntry /// Indicates an entry is about to be read from the archive. /// Meaningful properties: ArchiveName, EntriesTotal. /// /// /// /// /// ZipProgressEventType.Reading_AfterReadEntry /// Indicates an entry has just been read from the archive. /// Meaningful properties: ArchiveName, EntriesTotal, CurrentEntry. /// /// /// /// /// /// /// /// /// internal event EventHandler ReadProgress; private void OnReadStarted() { EventHandler rp = ReadProgress; if (rp != null) { var e = ReadProgressEventArgs.Started(ArchiveNameForEvent); rp(this, e); } } private void OnReadCompleted() { EventHandler rp = ReadProgress; if (rp != null) { var e = ReadProgressEventArgs.Completed(ArchiveNameForEvent); rp(this, e); } } internal void OnReadBytes(ZipEntry entry) { EventHandler rp = ReadProgress; if (rp != null) { var e = ReadProgressEventArgs.ByteUpdate(ArchiveNameForEvent, entry, ReadStream.Position, LengthOfReadStream); rp(this, e); } } internal void OnReadEntry(bool before, ZipEntry entry) { EventHandler rp = ReadProgress; if (rp != null) { ReadProgressEventArgs e = (before) ? ReadProgressEventArgs.Before(ArchiveNameForEvent, _entries.Count) : ReadProgressEventArgs.After(ArchiveNameForEvent, entry, _entries.Count); rp(this, e); } } private Int64 _lengthOfReadStream = -99; private Int64 LengthOfReadStream { get { if (_lengthOfReadStream == -99) { _lengthOfReadStream = (_ReadStreamIsOurs) ? SharedUtilities.GetFileLength(_name) : -1L; } return _lengthOfReadStream; } } #endregion #region Extract /// /// An event handler invoked before, during, and after extraction of /// entries in the zip archive. /// /// /// /// /// Depending on the particular event, different properties on the parameter are set. The following /// table summarizes the available EventTypes and the conditions under /// which this event handler is invoked with a /// ExtractProgressEventArgs with the given EventType. /// /// /// /// /// value of EntryType /// Meaning and conditions /// /// /// /// ZipProgressEventType.Extracting_BeforeExtractAll /// /// Set when ExtractAll() begins. The ArchiveName, Overwrite, and /// ExtractLocation properties are meaningful. /// /// /// /// ZipProgressEventType.Extracting_AfterExtractAll /// /// Set when ExtractAll() has completed. The ArchiveName, Overwrite, /// and ExtractLocation properties are meaningful. /// /// /// /// /// ZipProgressEventType.Extracting_BeforeExtractEntry /// /// Set when an Extract() on an entry in the ZipFile has begun. /// Properties that are meaningful: ArchiveName, EntriesTotal, /// CurrentEntry, Overwrite, ExtractLocation, EntriesExtracted. /// /// /// /// /// ZipProgressEventType.Extracting_AfterExtractEntry /// /// Set when an Extract() on an entry in the ZipFile has completed. /// Properties that are meaningful: ArchiveName, EntriesTotal, /// CurrentEntry, Overwrite, ExtractLocation, EntriesExtracted. /// /// /// /// /// ZipProgressEventType.Extracting_EntryBytesWritten /// /// Set within a call to Extract() on an entry in the ZipFile, as data /// is extracted for the entry. Properties that are meaningful: /// ArchiveName, CurrentEntry, BytesTransferred, TotalBytesToTransfer. /// /// /// /// /// ZipProgressEventType.Extracting_ExtractEntryWouldOverwrite /// /// Set within a call to Extract() on an entry in the ZipFile, when the /// extraction would overwrite an existing file. This event type is used /// only when ExtractExistingFileAction on the ZipFile or /// ZipEntry is set to InvokeExtractProgressEvent. /// /// /// /// /// /// /// /// /// /// private static bool justHadByteUpdate = false; /// public static void ExtractProgress(object sender, ExtractProgressEventArgs e) /// { /// if(e.EventType == ZipProgressEventType.Extracting_EntryBytesWritten) /// { /// if (justHadByteUpdate) /// Console.SetCursorPosition(0, Console.CursorTop); /// /// Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, e.TotalBytesToTransfer, /// e.BytesTransferred / (0.01 * e.TotalBytesToTransfer )); /// justHadByteUpdate = true; /// } /// else if(e.EventType == ZipProgressEventType.Extracting_BeforeExtractEntry) /// { /// if (justHadByteUpdate) /// Console.WriteLine(); /// Console.WriteLine("Extracting: {0}", e.CurrentEntry.FileName); /// justHadByteUpdate= false; /// } /// } /// /// public static ExtractZip(string zipToExtract, string directory) /// { /// string TargetDirectory= "extract"; /// using (var zip = ZipFile.Read(zipToExtract)) { /// zip.ExtractProgress += ExtractProgress; /// foreach (var e in zip1) /// { /// e.Extract(TargetDirectory, true); /// } /// } /// } /// /// /// /// Public Shared Sub Main(ByVal args As String()) /// Dim ZipToUnpack As String = "C1P3SML.zip" /// Dim TargetDir As String = "ExtractTest_Extract" /// Console.WriteLine("Extracting file {0} to {1}", ZipToUnpack, TargetDir) /// Using zip1 As ZipFile = ZipFile.Read(ZipToUnpack) /// AddHandler zip1.ExtractProgress, AddressOf MyExtractProgress /// Dim e As ZipEntry /// For Each e In zip1 /// e.Extract(TargetDir, True) /// Next /// End Using /// End Sub /// /// Private Shared justHadByteUpdate As Boolean = False /// /// Public Shared Sub MyExtractProgress(ByVal sender As Object, ByVal e As ExtractProgressEventArgs) /// If (e.EventType = ZipProgressEventType.Extracting_EntryBytesWritten) Then /// If ExtractTest.justHadByteUpdate Then /// Console.SetCursorPosition(0, Console.CursorTop) /// End If /// Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, e.TotalBytesToTransfer, (CDbl(e.BytesTransferred) / (0.01 * e.TotalBytesToTransfer))) /// ExtractTest.justHadByteUpdate = True /// ElseIf (e.EventType = ZipProgressEventType.Extracting_BeforeExtractEntry) Then /// If ExtractTest.justHadByteUpdate Then /// Console.WriteLine /// End If /// Console.WriteLine("Extracting: {0}", e.CurrentEntry.FileName) /// ExtractTest.justHadByteUpdate = False /// End If /// End Sub /// /// /// /// /// /// internal event EventHandler ExtractProgress; private void OnExtractEntry(int current, bool before, ZipEntry currentEntry, string path) { EventHandler ep = ExtractProgress; if (ep != null) { var e = new ExtractProgressEventArgs(ArchiveNameForEvent, before, _entries.Count, current, currentEntry, path); ep(this, e); if (e.Cancel) _extractOperationCanceled = true; } } // Can be called from within ZipEntry._ExtractOne. internal bool OnExtractBlock(ZipEntry entry, Int64 bytesWritten, Int64 totalBytesToWrite) { EventHandler ep = ExtractProgress; if (ep != null) { var e = ExtractProgressEventArgs.ByteUpdate(ArchiveNameForEvent, entry, bytesWritten, totalBytesToWrite); ep(this, e); if (e.Cancel) _extractOperationCanceled = true; } return _extractOperationCanceled; } // Can be called from within ZipEntry.InternalExtract. internal bool OnSingleEntryExtract(ZipEntry entry, string path, bool before) { EventHandler ep = ExtractProgress; if (ep != null) { var e = (before) ? ExtractProgressEventArgs.BeforeExtractEntry(ArchiveNameForEvent, entry, path) : ExtractProgressEventArgs.AfterExtractEntry(ArchiveNameForEvent, entry, path); ep(this, e); if (e.Cancel) _extractOperationCanceled = true; } return _extractOperationCanceled; } internal bool OnExtractExisting(ZipEntry entry, string path) { EventHandler ep = ExtractProgress; if (ep != null) { var e = ExtractProgressEventArgs.ExtractExisting(ArchiveNameForEvent, entry, path); ep(this, e); if (e.Cancel) _extractOperationCanceled = true; } return _extractOperationCanceled; } private void OnExtractAllCompleted(string path) { EventHandler ep = ExtractProgress; if (ep != null) { var e = ExtractProgressEventArgs.ExtractAllCompleted(ArchiveNameForEvent, path ); ep(this, e); } } private void OnExtractAllStarted(string path) { EventHandler ep = ExtractProgress; if (ep != null) { var e = ExtractProgressEventArgs.ExtractAllStarted(ArchiveNameForEvent, path ); ep(this, e); } } #endregion #region Add /// /// An event handler invoked before, during, and after Adding entries to a zip archive. /// /// /// /// Adding a large number of entries to a zip file can take a long /// time. For example, when calling on a /// directory that contains 50,000 files, it could take 3 minutes or so. /// This event handler allws an application to track the progress of the Add /// operation, and to optionally cancel a lengthy Add operation. /// /// /// /// /// /// int _numEntriesToAdd= 0; /// int _numEntriesAdded= 0; /// void AddProgressHandler(object sender, AddProgressEventArgs e) /// { /// switch (e.EventType) /// { /// case ZipProgressEventType.Adding_Started: /// Console.WriteLine("Adding files to the zip..."); /// break; /// case ZipProgressEventType.Adding_AfterAddEntry: /// _numEntriesAdded++; /// Console.WriteLine(String.Format("Adding file {0}/{1} :: {2}", /// _numEntriesAdded, _numEntriesToAdd, e.CurrentEntry.FileName)); /// break; /// case ZipProgressEventType.Adding_Completed: /// Console.WriteLine("Added all files"); /// break; /// } /// } /// /// void CreateTheZip() /// { /// using (ZipFile zip = new ZipFile()) /// { /// zip.AddProgress += AddProgressHandler; /// zip.AddDirectory(System.IO.Path.GetFileName(DirToZip)); /// zip.Save(ZipFileToCreate); /// } /// } /// /// /// /// /// /// Private Sub AddProgressHandler(ByVal sender As Object, ByVal e As AddProgressEventArgs) /// Select Case e.EventType /// Case ZipProgressEventType.Adding_Started /// Console.WriteLine("Adding files to the zip...") /// Exit Select /// Case ZipProgressEventType.Adding_AfterAddEntry /// Console.WriteLine(String.Format("Adding file {0}", e.CurrentEntry.FileName)) /// Exit Select /// Case ZipProgressEventType.Adding_Completed /// Console.WriteLine("Added all files") /// Exit Select /// End Select /// End Sub /// /// Sub CreateTheZip() /// Using zip as ZipFile = New ZipFile /// AddHandler zip.AddProgress, AddressOf AddProgressHandler /// zip.AddDirectory(System.IO.Path.GetFileName(DirToZip)) /// zip.Save(ZipFileToCreate); /// End Using /// End Sub /// /// /// /// /// /// /// /// internal event EventHandler AddProgress; private void OnAddStarted() { EventHandler ap = AddProgress; if (ap != null) { var e = AddProgressEventArgs.Started(ArchiveNameForEvent); ap(this, e); if (e.Cancel) // workitem 13371 _addOperationCanceled = true; } } private void OnAddCompleted() { EventHandler ap = AddProgress; if (ap != null) { var e = AddProgressEventArgs.Completed(ArchiveNameForEvent); ap(this, e); } } internal void AfterAddEntry(ZipEntry entry) { EventHandler ap = AddProgress; if (ap != null) { var e = AddProgressEventArgs.AfterEntry(ArchiveNameForEvent, entry, _entries.Count); ap(this, e); if (e.Cancel) // workitem 13371 _addOperationCanceled = true; } } #endregion #region Error /// /// An event that is raised when an error occurs during open or read of files /// while saving a zip archive. /// /// /// /// /// Errors can occur as a file is being saved to the zip archive. For /// example, the File.Open may fail, or a File.Read may fail, because of /// lock conflicts or other reasons. If you add a handler to this event, /// you can handle such errors in your own code. If you don't add a /// handler, the library will throw an exception if it encounters an I/O /// error during a call to Save(). /// /// /// /// Setting a handler implicitly sets to /// ZipErrorAction.InvokeErrorEvent. /// /// /// /// The handler you add applies to all items that are /// subsequently added to the ZipFile instance. If you set this /// property after you have added items to the ZipFile, but before you /// have called Save(), errors that occur while saving those items /// will not cause the error handler to be invoked. /// /// /// /// If you want to handle any errors that occur with any entry in the zip /// file using the same error handler, then add your error handler once, /// before adding any entries to the zip archive. /// /// /// /// In the error handler method, you need to set the property on the /// ZipErrorEventArgs.CurrentEntry. This communicates back to /// DotNetZip what you would like to do with this particular error. Within /// an error handler, if you set the ZipEntry.ZipErrorAction property /// on the ZipEntry to ZipErrorAction.InvokeErrorEvent or if /// you don't set it at all, the library will throw the exception. (It is the /// same as if you had set the ZipEntry.ZipErrorAction property on the /// ZipEntry to ZipErrorAction.Throw.) If you set the /// ZipErrorEventArgs.Cancel to true, the entire Save() will be /// canceled. /// /// /// /// In the case that you use ZipErrorAction.Skip, implying that /// you want to skip the entry for which there's been an error, DotNetZip /// tries to seek backwards in the output stream, and truncate all bytes /// written on behalf of that particular entry. This works only if the /// output stream is seekable. It will not work, for example, when using /// ASPNET's Response.OutputStream. /// /// /// /// /// /// /// This example shows how to use an event handler to handle /// errors during save of the zip file. /// /// /// public static void MyZipError(object sender, ZipErrorEventArgs e) /// { /// Console.WriteLine("Error saving {0}...", e.FileName); /// Console.WriteLine(" Exception: {0}", e.exception); /// ZipEntry entry = e.CurrentEntry; /// string response = null; /// // Ask the user whether he wants to skip this error or not /// do /// { /// Console.Write("Retry, Skip, Throw, or Cancel ? (R/S/T/C) "); /// response = Console.ReadLine(); /// Console.WriteLine(); /// /// } while (response != null && /// response[0]!='S' && response[0]!='s' && /// response[0]!='R' && response[0]!='r' && /// response[0]!='T' && response[0]!='t' && /// response[0]!='C' && response[0]!='c'); /// /// e.Cancel = (response[0]=='C' || response[0]=='c'); /// /// if (response[0]=='S' || response[0]=='s') /// entry.ZipErrorAction = ZipErrorAction.Skip; /// else if (response[0]=='R' || response[0]=='r') /// entry.ZipErrorAction = ZipErrorAction.Retry; /// else if (response[0]=='T' || response[0]=='t') /// entry.ZipErrorAction = ZipErrorAction.Throw; /// } /// /// public void SaveTheFile() /// { /// string directoryToZip = "fodder"; /// string directoryInArchive = "files"; /// string zipFileToCreate = "Archive.zip"; /// using (var zip = new ZipFile()) /// { /// // set the event handler before adding any entries /// zip.ZipError += MyZipError; /// zip.AddDirectory(directoryToZip, directoryInArchive); /// zip.Save(zipFileToCreate); /// } /// } /// /// /// /// Private Sub MyZipError(ByVal sender As Object, ByVal e As Ionic.Zip.ZipErrorEventArgs) /// ' At this point, the application could prompt the user for an action to take. /// ' But in this case, this application will simply automatically skip the file, in case of error. /// Console.WriteLine("Zip Error, entry {0}", e.CurrentEntry.FileName) /// Console.WriteLine(" Exception: {0}", e.exception) /// ' set the desired ZipErrorAction on the CurrentEntry to communicate that to DotNetZip /// e.CurrentEntry.ZipErrorAction = Zip.ZipErrorAction.Skip /// End Sub /// /// Public Sub SaveTheFile() /// Dim directoryToZip As String = "fodder" /// Dim directoryInArchive As String = "files" /// Dim zipFileToCreate as String = "Archive.zip" /// Using zipArchive As ZipFile = New ZipFile /// ' set the event handler before adding any entries /// AddHandler zipArchive.ZipError, AddressOf MyZipError /// zipArchive.AddDirectory(directoryToZip, directoryInArchive) /// zipArchive.Save(zipFileToCreate) /// End Using /// End Sub /// /// /// /// /// internal event EventHandler ZipError; internal bool OnZipErrorSaving(ZipEntry entry, Exception exc) { if (ZipError != null) { lock (LOCK) { var e = ZipErrorEventArgs.Saving(this.Name, entry, exc); ZipError(this, e); if (e.Cancel) _saveOperationCanceled = true; } } return _saveOperationCanceled; } #endregion } }