ZipFile.Events.cs 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219
  1. // ZipFile.Events.cs
  2. // ------------------------------------------------------------------
  3. //
  4. // Copyright (c) 2008, 2009, 2011 Dino Chiesa .
  5. // All rights reserved.
  6. //
  7. // This code module is part of DotNetZip, a zipfile class library.
  8. //
  9. // ------------------------------------------------------------------
  10. //
  11. // This code is licensed under the Microsoft Public License.
  12. // See the file License.txt for the license details.
  13. // More info on: http://dotnetzip.codeplex.com
  14. //
  15. // ------------------------------------------------------------------
  16. //
  17. // last saved (in emacs):
  18. // Time-stamp: <2011-July-09 08:42:35>
  19. //
  20. // ------------------------------------------------------------------
  21. //
  22. // This module defines the methods for issuing events from the ZipFile class.
  23. //
  24. // ------------------------------------------------------------------
  25. //
  26. using System;
  27. using System.IO;
  28. namespace Ionic.Zip
  29. {
  30. public partial class ZipFile
  31. {
  32. private string ArchiveNameForEvent
  33. {
  34. get
  35. {
  36. return (_name != null) ? _name : "(stream)";
  37. }
  38. }
  39. #region Save
  40. /// <summary>
  41. /// An event handler invoked when a Save() starts, before and after each
  42. /// entry has been written to the archive, when a Save() completes, and
  43. /// during other Save events.
  44. /// </summary>
  45. ///
  46. /// <remarks>
  47. /// <para>
  48. /// Depending on the particular event, different properties on the <see
  49. /// cref="SaveProgressEventArgs"/> parameter are set. The following
  50. /// table summarizes the available EventTypes and the conditions under
  51. /// which this event handler is invoked with a
  52. /// <c>SaveProgressEventArgs</c> with the given EventType.
  53. /// </para>
  54. ///
  55. /// <list type="table">
  56. /// <listheader>
  57. /// <term>value of EntryType</term>
  58. /// <description>Meaning and conditions</description>
  59. /// </listheader>
  60. ///
  61. /// <item>
  62. /// <term>ZipProgressEventType.Saving_Started</term>
  63. /// <description>Fired when ZipFile.Save() begins.
  64. /// </description>
  65. /// </item>
  66. ///
  67. /// <item>
  68. /// <term>ZipProgressEventType.Saving_BeforeSaveEntry</term>
  69. /// <description>
  70. /// Fired within ZipFile.Save(), just before writing data for each
  71. /// particular entry.
  72. /// </description>
  73. /// </item>
  74. ///
  75. /// <item>
  76. /// <term>ZipProgressEventType.Saving_AfterSaveEntry</term>
  77. /// <description>
  78. /// Fired within ZipFile.Save(), just after having finished writing data
  79. /// for each particular entry.
  80. /// </description>
  81. /// </item>
  82. ///
  83. /// <item>
  84. /// <term>ZipProgressEventType.Saving_Completed</term>
  85. /// <description>Fired when ZipFile.Save() has completed.
  86. /// </description>
  87. /// </item>
  88. ///
  89. /// <item>
  90. /// <term>ZipProgressEventType.Saving_AfterSaveTempArchive</term>
  91. /// <description>
  92. /// Fired after the temporary file has been created. This happens only
  93. /// when saving to a disk file. This event will not be invoked when
  94. /// saving to a stream.
  95. /// </description>
  96. /// </item>
  97. ///
  98. /// <item>
  99. /// <term>ZipProgressEventType.Saving_BeforeRenameTempArchive</term>
  100. /// <description>
  101. /// Fired just before renaming the temporary file to the permanent
  102. /// location. This happens only when saving to a disk file. This event
  103. /// will not be invoked when saving to a stream.
  104. /// </description>
  105. /// </item>
  106. ///
  107. /// <item>
  108. /// <term>ZipProgressEventType.Saving_AfterRenameTempArchive</term>
  109. /// <description>
  110. /// Fired just after renaming the temporary file to the permanent
  111. /// location. This happens only when saving to a disk file. This event
  112. /// will not be invoked when saving to a stream.
  113. /// </description>
  114. /// </item>
  115. ///
  116. /// <item>
  117. /// <term>ZipProgressEventType.Saving_AfterCompileSelfExtractor</term>
  118. /// <description>
  119. /// Fired after a self-extracting archive has finished compiling. This
  120. /// EventType is used only within SaveSelfExtractor().
  121. /// </description>
  122. /// </item>
  123. ///
  124. /// <item>
  125. /// <term>ZipProgressEventType.Saving_BytesRead</term>
  126. /// <description>
  127. /// Set during the save of a particular entry, to update progress of the
  128. /// Save(). When this EventType is set, the BytesTransferred is the
  129. /// number of bytes that have been read from the source stream. The
  130. /// TotalBytesToTransfer is the number of bytes in the uncompressed
  131. /// file.
  132. /// </description>
  133. /// </item>
  134. ///
  135. /// </list>
  136. /// </remarks>
  137. ///
  138. /// <example>
  139. ///
  140. /// This example uses an anonymous method to handle the
  141. /// SaveProgress event, by updating a progress bar.
  142. ///
  143. /// <code lang="C#">
  144. /// progressBar1.Value = 0;
  145. /// progressBar1.Max = listbox1.Items.Count;
  146. /// using (ZipFile zip = new ZipFile())
  147. /// {
  148. /// // listbox1 contains a list of filenames
  149. /// zip.AddFiles(listbox1.Items);
  150. ///
  151. /// // do the progress bar:
  152. /// zip.SaveProgress += (sender, e) => {
  153. /// if (e.EventType == ZipProgressEventType.Saving_BeforeWriteEntry) {
  154. /// progressBar1.PerformStep();
  155. /// }
  156. /// };
  157. ///
  158. /// zip.Save(fs);
  159. /// }
  160. /// </code>
  161. /// </example>
  162. ///
  163. /// <example>
  164. /// This example uses a named method as the
  165. /// <c>SaveProgress</c> event handler, to update the user, in a
  166. /// console-based application.
  167. ///
  168. /// <code lang="C#">
  169. /// static bool justHadByteUpdate= false;
  170. /// public static void SaveProgress(object sender, SaveProgressEventArgs e)
  171. /// {
  172. /// if (e.EventType == ZipProgressEventType.Saving_Started)
  173. /// Console.WriteLine("Saving: {0}", e.ArchiveName);
  174. ///
  175. /// else if (e.EventType == ZipProgressEventType.Saving_Completed)
  176. /// {
  177. /// justHadByteUpdate= false;
  178. /// Console.WriteLine();
  179. /// Console.WriteLine("Done: {0}", e.ArchiveName);
  180. /// }
  181. ///
  182. /// else if (e.EventType == ZipProgressEventType.Saving_BeforeWriteEntry)
  183. /// {
  184. /// if (justHadByteUpdate)
  185. /// Console.WriteLine();
  186. /// Console.WriteLine(" Writing: {0} ({1}/{2})",
  187. /// e.CurrentEntry.FileName, e.EntriesSaved, e.EntriesTotal);
  188. /// justHadByteUpdate= false;
  189. /// }
  190. ///
  191. /// else if (e.EventType == ZipProgressEventType.Saving_EntryBytesRead)
  192. /// {
  193. /// if (justHadByteUpdate)
  194. /// Console.SetCursorPosition(0, Console.CursorTop);
  195. /// Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, e.TotalBytesToTransfer,
  196. /// e.BytesTransferred / (0.01 * e.TotalBytesToTransfer ));
  197. /// justHadByteUpdate= true;
  198. /// }
  199. /// }
  200. ///
  201. /// public static ZipUp(string targetZip, string directory)
  202. /// {
  203. /// using (var zip = new ZipFile()) {
  204. /// zip.SaveProgress += SaveProgress;
  205. /// zip.AddDirectory(directory);
  206. /// zip.Save(targetZip);
  207. /// }
  208. /// }
  209. ///
  210. /// </code>
  211. ///
  212. /// <code lang="VB">
  213. /// Public Sub ZipUp(ByVal targetZip As String, ByVal directory As String)
  214. /// Using zip As ZipFile = New ZipFile
  215. /// AddHandler zip.SaveProgress, AddressOf MySaveProgress
  216. /// zip.AddDirectory(directory)
  217. /// zip.Save(targetZip)
  218. /// End Using
  219. /// End Sub
  220. ///
  221. /// Private Shared justHadByteUpdate As Boolean = False
  222. ///
  223. /// Public Shared Sub MySaveProgress(ByVal sender As Object, ByVal e As SaveProgressEventArgs)
  224. /// If (e.EventType Is ZipProgressEventType.Saving_Started) Then
  225. /// Console.WriteLine("Saving: {0}", e.ArchiveName)
  226. ///
  227. /// ElseIf (e.EventType Is ZipProgressEventType.Saving_Completed) Then
  228. /// justHadByteUpdate = False
  229. /// Console.WriteLine
  230. /// Console.WriteLine("Done: {0}", e.ArchiveName)
  231. ///
  232. /// ElseIf (e.EventType Is ZipProgressEventType.Saving_BeforeWriteEntry) Then
  233. /// If justHadByteUpdate Then
  234. /// Console.WriteLine
  235. /// End If
  236. /// Console.WriteLine(" Writing: {0} ({1}/{2})", e.CurrentEntry.FileName, e.EntriesSaved, e.EntriesTotal)
  237. /// justHadByteUpdate = False
  238. ///
  239. /// ElseIf (e.EventType Is ZipProgressEventType.Saving_EntryBytesRead) Then
  240. /// If justHadByteUpdate Then
  241. /// Console.SetCursorPosition(0, Console.CursorTop)
  242. /// End If
  243. /// Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, _
  244. /// e.TotalBytesToTransfer, _
  245. /// (CDbl(e.BytesTransferred) / (0.01 * e.TotalBytesToTransfer)))
  246. /// justHadByteUpdate = True
  247. /// End If
  248. /// End Sub
  249. /// </code>
  250. /// </example>
  251. ///
  252. /// <example>
  253. ///
  254. /// This is a more complete example of using the SaveProgress
  255. /// events in a Windows Forms application, with a
  256. /// Thread object.
  257. ///
  258. /// <code lang="C#">
  259. /// delegate void SaveEntryProgress(SaveProgressEventArgs e);
  260. /// delegate void ButtonClick(object sender, EventArgs e);
  261. ///
  262. /// public class WorkerOptions
  263. /// {
  264. /// public string ZipName;
  265. /// public string Folder;
  266. /// public string Encoding;
  267. /// public string Comment;
  268. /// public int ZipFlavor;
  269. /// public Zip64Option Zip64;
  270. /// }
  271. ///
  272. /// private int _progress2MaxFactor;
  273. /// private bool _saveCanceled;
  274. /// private long _totalBytesBeforeCompress;
  275. /// private long _totalBytesAfterCompress;
  276. /// private Thread _workerThread;
  277. ///
  278. ///
  279. /// private void btnZipup_Click(object sender, EventArgs e)
  280. /// {
  281. /// KickoffZipup();
  282. /// }
  283. ///
  284. /// private void btnCancel_Click(object sender, EventArgs e)
  285. /// {
  286. /// if (this.lblStatus.InvokeRequired)
  287. /// {
  288. /// this.lblStatus.Invoke(new ButtonClick(this.btnCancel_Click), new object[] { sender, e });
  289. /// }
  290. /// else
  291. /// {
  292. /// _saveCanceled = true;
  293. /// lblStatus.Text = "Canceled...";
  294. /// ResetState();
  295. /// }
  296. /// }
  297. ///
  298. /// private void KickoffZipup()
  299. /// {
  300. /// _folderName = tbDirName.Text;
  301. ///
  302. /// if (_folderName == null || _folderName == "") return;
  303. /// if (this.tbZipName.Text == null || this.tbZipName.Text == "") return;
  304. ///
  305. /// // check for existence of the zip file:
  306. /// if (System.IO.File.Exists(this.tbZipName.Text))
  307. /// {
  308. /// var dlgResult = MessageBox.Show(String.Format("The file you have specified ({0}) already exists." +
  309. /// " Do you want to overwrite this file?", this.tbZipName.Text),
  310. /// "Confirmation is Required", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
  311. /// if (dlgResult != DialogResult.Yes) return;
  312. /// System.IO.File.Delete(this.tbZipName.Text);
  313. /// }
  314. ///
  315. /// _saveCanceled = false;
  316. /// _nFilesCompleted = 0;
  317. /// _totalBytesAfterCompress = 0;
  318. /// _totalBytesBeforeCompress = 0;
  319. /// this.btnOk.Enabled = false;
  320. /// this.btnOk.Text = "Zipping...";
  321. /// this.btnCancel.Enabled = true;
  322. /// lblStatus.Text = "Zipping...";
  323. ///
  324. /// var options = new WorkerOptions
  325. /// {
  326. /// ZipName = this.tbZipName.Text,
  327. /// Folder = _folderName,
  328. /// Encoding = "ibm437"
  329. /// };
  330. ///
  331. /// if (this.comboBox1.SelectedIndex != 0)
  332. /// {
  333. /// options.Encoding = this.comboBox1.SelectedItem.ToString();
  334. /// }
  335. ///
  336. /// if (this.radioFlavorSfxCmd.Checked)
  337. /// options.ZipFlavor = 2;
  338. /// else if (this.radioFlavorSfxGui.Checked)
  339. /// options.ZipFlavor = 1;
  340. /// else options.ZipFlavor = 0;
  341. ///
  342. /// if (this.radioZip64AsNecessary.Checked)
  343. /// options.Zip64 = Zip64Option.AsNecessary;
  344. /// else if (this.radioZip64Always.Checked)
  345. /// options.Zip64 = Zip64Option.Always;
  346. /// else options.Zip64 = Zip64Option.Never;
  347. ///
  348. /// options.Comment = String.Format("Encoding:{0} || Flavor:{1} || ZIP64:{2}\r\nCreated at {3} || {4}\r\n",
  349. /// options.Encoding,
  350. /// FlavorToString(options.ZipFlavor),
  351. /// options.Zip64.ToString(),
  352. /// System.DateTime.Now.ToString("yyyy-MMM-dd HH:mm:ss"),
  353. /// this.Text);
  354. ///
  355. /// if (this.tbComment.Text != TB_COMMENT_NOTE)
  356. /// options.Comment += this.tbComment.Text;
  357. ///
  358. /// _workerThread = new Thread(this.DoSave);
  359. /// _workerThread.Name = "Zip Saver thread";
  360. /// _workerThread.Start(options);
  361. /// this.Cursor = Cursors.WaitCursor;
  362. /// }
  363. ///
  364. ///
  365. /// private void DoSave(Object p)
  366. /// {
  367. /// WorkerOptions options = p as WorkerOptions;
  368. /// try
  369. /// {
  370. /// using (var zip1 = new ZipFile())
  371. /// {
  372. /// zip1.ProvisionalAlternateEncoding = System.Text.Encoding.GetEncoding(options.Encoding);
  373. /// zip1.Comment = options.Comment;
  374. /// zip1.AddDirectory(options.Folder);
  375. /// _entriesToZip = zip1.EntryFileNames.Count;
  376. /// SetProgressBars();
  377. /// zip1.SaveProgress += this.zip1_SaveProgress;
  378. ///
  379. /// zip1.UseZip64WhenSaving = options.Zip64;
  380. ///
  381. /// if (options.ZipFlavor == 1)
  382. /// zip1.SaveSelfExtractor(options.ZipName, SelfExtractorFlavor.WinFormsApplication);
  383. /// else if (options.ZipFlavor == 2)
  384. /// zip1.SaveSelfExtractor(options.ZipName, SelfExtractorFlavor.ConsoleApplication);
  385. /// else
  386. /// zip1.Save(options.ZipName);
  387. /// }
  388. /// }
  389. /// catch (System.Exception exc1)
  390. /// {
  391. /// MessageBox.Show(String.Format("Exception while zipping: {0}", exc1.Message));
  392. /// btnCancel_Click(null, null);
  393. /// }
  394. /// }
  395. ///
  396. ///
  397. ///
  398. /// void zip1_SaveProgress(object sender, SaveProgressEventArgs e)
  399. /// {
  400. /// switch (e.EventType)
  401. /// {
  402. /// case ZipProgressEventType.Saving_AfterWriteEntry:
  403. /// StepArchiveProgress(e);
  404. /// break;
  405. /// case ZipProgressEventType.Saving_EntryBytesRead:
  406. /// StepEntryProgress(e);
  407. /// break;
  408. /// case ZipProgressEventType.Saving_Completed:
  409. /// SaveCompleted();
  410. /// break;
  411. /// case ZipProgressEventType.Saving_AfterSaveTempArchive:
  412. /// // this event only occurs when saving an SFX file
  413. /// TempArchiveSaved();
  414. /// break;
  415. /// }
  416. /// if (_saveCanceled)
  417. /// e.Cancel = true;
  418. /// }
  419. ///
  420. ///
  421. ///
  422. /// private void StepArchiveProgress(SaveProgressEventArgs e)
  423. /// {
  424. /// if (this.progressBar1.InvokeRequired)
  425. /// {
  426. /// this.progressBar1.Invoke(new SaveEntryProgress(this.StepArchiveProgress), new object[] { e });
  427. /// }
  428. /// else
  429. /// {
  430. /// if (!_saveCanceled)
  431. /// {
  432. /// _nFilesCompleted++;
  433. /// this.progressBar1.PerformStep();
  434. /// _totalBytesAfterCompress += e.CurrentEntry.CompressedSize;
  435. /// _totalBytesBeforeCompress += e.CurrentEntry.UncompressedSize;
  436. ///
  437. /// // reset the progress bar for the entry:
  438. /// this.progressBar2.Value = this.progressBar2.Maximum = 1;
  439. ///
  440. /// this.Update();
  441. /// }
  442. /// }
  443. /// }
  444. ///
  445. ///
  446. /// private void StepEntryProgress(SaveProgressEventArgs e)
  447. /// {
  448. /// if (this.progressBar2.InvokeRequired)
  449. /// {
  450. /// this.progressBar2.Invoke(new SaveEntryProgress(this.StepEntryProgress), new object[] { e });
  451. /// }
  452. /// else
  453. /// {
  454. /// if (!_saveCanceled)
  455. /// {
  456. /// if (this.progressBar2.Maximum == 1)
  457. /// {
  458. /// // reset
  459. /// Int64 max = e.TotalBytesToTransfer;
  460. /// _progress2MaxFactor = 0;
  461. /// while (max > System.Int32.MaxValue)
  462. /// {
  463. /// max /= 2;
  464. /// _progress2MaxFactor++;
  465. /// }
  466. /// this.progressBar2.Maximum = (int)max;
  467. /// lblStatus.Text = String.Format("{0} of {1} files...({2})",
  468. /// _nFilesCompleted + 1, _entriesToZip, e.CurrentEntry.FileName);
  469. /// }
  470. ///
  471. /// int xferred = e.BytesTransferred >> _progress2MaxFactor;
  472. ///
  473. /// this.progressBar2.Value = (xferred >= this.progressBar2.Maximum)
  474. /// ? this.progressBar2.Maximum
  475. /// : xferred;
  476. ///
  477. /// this.Update();
  478. /// }
  479. /// }
  480. /// }
  481. ///
  482. /// private void SaveCompleted()
  483. /// {
  484. /// if (this.lblStatus.InvokeRequired)
  485. /// {
  486. /// this.lblStatus.Invoke(new MethodInvoker(this.SaveCompleted));
  487. /// }
  488. /// else
  489. /// {
  490. /// lblStatus.Text = String.Format("Done, Compressed {0} files, {1:N0}% of original.",
  491. /// _nFilesCompleted, (100.00 * _totalBytesAfterCompress) / _totalBytesBeforeCompress);
  492. /// ResetState();
  493. /// }
  494. /// }
  495. ///
  496. /// private void ResetState()
  497. /// {
  498. /// this.btnCancel.Enabled = false;
  499. /// this.btnOk.Enabled = true;
  500. /// this.btnOk.Text = "Zip it!";
  501. /// this.progressBar1.Value = 0;
  502. /// this.progressBar2.Value = 0;
  503. /// this.Cursor = Cursors.Default;
  504. /// if (!_workerThread.IsAlive)
  505. /// _workerThread.Join();
  506. /// }
  507. /// </code>
  508. ///
  509. /// </example>
  510. ///
  511. /// <seealso cref="Ionic.Zip.ZipFile.ReadProgress"/>
  512. /// <seealso cref="Ionic.Zip.ZipFile.AddProgress"/>
  513. /// <seealso cref="Ionic.Zip.ZipFile.ExtractProgress"/>
  514. public event EventHandler<SaveProgressEventArgs> SaveProgress;
  515. internal bool OnSaveBlock(ZipEntry entry, Int64 bytesXferred, Int64 totalBytesToXfer)
  516. {
  517. EventHandler<SaveProgressEventArgs> sp = SaveProgress;
  518. if (sp != null)
  519. {
  520. var e = SaveProgressEventArgs.ByteUpdate(ArchiveNameForEvent, entry,
  521. bytesXferred, totalBytesToXfer);
  522. sp(this, e);
  523. if (e.Cancel)
  524. _saveOperationCanceled = true;
  525. }
  526. return _saveOperationCanceled;
  527. }
  528. private void OnSaveEntry(int current, ZipEntry entry, bool before)
  529. {
  530. EventHandler<SaveProgressEventArgs> sp = SaveProgress;
  531. if (sp != null)
  532. {
  533. var e = new SaveProgressEventArgs(ArchiveNameForEvent, before, _entries.Count, current, entry);
  534. sp(this, e);
  535. if (e.Cancel)
  536. _saveOperationCanceled = true;
  537. }
  538. }
  539. private void OnSaveEvent(ZipProgressEventType eventFlavor)
  540. {
  541. EventHandler<SaveProgressEventArgs> sp = SaveProgress;
  542. if (sp != null)
  543. {
  544. var e = new SaveProgressEventArgs(ArchiveNameForEvent, eventFlavor);
  545. sp(this, e);
  546. if (e.Cancel)
  547. _saveOperationCanceled = true;
  548. }
  549. }
  550. private void OnSaveStarted()
  551. {
  552. EventHandler<SaveProgressEventArgs> sp = SaveProgress;
  553. if (sp != null)
  554. {
  555. var e = SaveProgressEventArgs.Started(ArchiveNameForEvent);
  556. sp(this, e);
  557. if (e.Cancel)
  558. _saveOperationCanceled = true;
  559. }
  560. }
  561. private void OnSaveCompleted()
  562. {
  563. EventHandler<SaveProgressEventArgs> sp = SaveProgress;
  564. if (sp != null)
  565. {
  566. var e = SaveProgressEventArgs.Completed(ArchiveNameForEvent);
  567. sp(this, e);
  568. }
  569. }
  570. #endregion
  571. #region Read
  572. /// <summary>
  573. /// An event handler invoked before, during, and after the reading of a zip archive.
  574. /// </summary>
  575. ///
  576. /// <remarks>
  577. /// <para>
  578. /// Depending on the particular event being signaled, different properties on the
  579. /// <see cref="ReadProgressEventArgs"/> parameter are set. The following table
  580. /// summarizes the available EventTypes and the conditions under which this
  581. /// event handler is invoked with a <c>ReadProgressEventArgs</c> with the given EventType.
  582. /// </para>
  583. ///
  584. /// <list type="table">
  585. /// <listheader>
  586. /// <term>value of EntryType</term>
  587. /// <description>Meaning and conditions</description>
  588. /// </listheader>
  589. ///
  590. /// <item>
  591. /// <term>ZipProgressEventType.Reading_Started</term>
  592. /// <description>Fired just as ZipFile.Read() begins. Meaningful properties: ArchiveName.
  593. /// </description>
  594. /// </item>
  595. ///
  596. /// <item>
  597. /// <term>ZipProgressEventType.Reading_Completed</term>
  598. /// <description>Fired when ZipFile.Read() has completed. Meaningful properties: ArchiveName.
  599. /// </description>
  600. /// </item>
  601. ///
  602. /// <item>
  603. /// <term>ZipProgressEventType.Reading_ArchiveBytesRead</term>
  604. /// <description>Fired while reading, updates the number of bytes read for the entire archive.
  605. /// Meaningful properties: ArchiveName, CurrentEntry, BytesTransferred, TotalBytesToTransfer.
  606. /// </description>
  607. /// </item>
  608. ///
  609. /// <item>
  610. /// <term>ZipProgressEventType.Reading_BeforeReadEntry</term>
  611. /// <description>Indicates an entry is about to be read from the archive.
  612. /// Meaningful properties: ArchiveName, EntriesTotal.
  613. /// </description>
  614. /// </item>
  615. ///
  616. /// <item>
  617. /// <term>ZipProgressEventType.Reading_AfterReadEntry</term>
  618. /// <description>Indicates an entry has just been read from the archive.
  619. /// Meaningful properties: ArchiveName, EntriesTotal, CurrentEntry.
  620. /// </description>
  621. /// </item>
  622. ///
  623. /// </list>
  624. /// </remarks>
  625. ///
  626. /// <seealso cref="Ionic.Zip.ZipFile.SaveProgress"/>
  627. /// <seealso cref="Ionic.Zip.ZipFile.AddProgress"/>
  628. /// <seealso cref="Ionic.Zip.ZipFile.ExtractProgress"/>
  629. public event EventHandler<ReadProgressEventArgs> ReadProgress;
  630. private void OnReadStarted()
  631. {
  632. EventHandler<ReadProgressEventArgs> rp = ReadProgress;
  633. if (rp != null)
  634. {
  635. var e = ReadProgressEventArgs.Started(ArchiveNameForEvent);
  636. rp(this, e);
  637. }
  638. }
  639. private void OnReadCompleted()
  640. {
  641. EventHandler<ReadProgressEventArgs> rp = ReadProgress;
  642. if (rp != null)
  643. {
  644. var e = ReadProgressEventArgs.Completed(ArchiveNameForEvent);
  645. rp(this, e);
  646. }
  647. }
  648. internal void OnReadBytes(ZipEntry entry)
  649. {
  650. EventHandler<ReadProgressEventArgs> rp = ReadProgress;
  651. if (rp != null)
  652. {
  653. var e = ReadProgressEventArgs.ByteUpdate(ArchiveNameForEvent,
  654. entry,
  655. ReadStream.Position,
  656. LengthOfReadStream);
  657. rp(this, e);
  658. }
  659. }
  660. internal void OnReadEntry(bool before, ZipEntry entry)
  661. {
  662. EventHandler<ReadProgressEventArgs> rp = ReadProgress;
  663. if (rp != null)
  664. {
  665. ReadProgressEventArgs e = (before)
  666. ? ReadProgressEventArgs.Before(ArchiveNameForEvent, _entries.Count)
  667. : ReadProgressEventArgs.After(ArchiveNameForEvent, entry, _entries.Count);
  668. rp(this, e);
  669. }
  670. }
  671. private Int64 _lengthOfReadStream = -99;
  672. private Int64 LengthOfReadStream
  673. {
  674. get
  675. {
  676. if (_lengthOfReadStream == -99)
  677. {
  678. _lengthOfReadStream = (_ReadStreamIsOurs)
  679. ? SharedUtilities.GetFileLength(_name)
  680. : -1L;
  681. }
  682. return _lengthOfReadStream;
  683. }
  684. }
  685. #endregion
  686. #region Extract
  687. /// <summary>
  688. /// An event handler invoked before, during, and after extraction of
  689. /// entries in the zip archive.
  690. /// </summary>
  691. ///
  692. /// <remarks>
  693. /// <para>
  694. /// Depending on the particular event, different properties on the <see
  695. /// cref="ExtractProgressEventArgs"/> parameter are set. The following
  696. /// table summarizes the available EventTypes and the conditions under
  697. /// which this event handler is invoked with a
  698. /// <c>ExtractProgressEventArgs</c> with the given EventType.
  699. /// </para>
  700. ///
  701. /// <list type="table">
  702. /// <listheader>
  703. /// <term>value of EntryType</term>
  704. /// <description>Meaning and conditions</description>
  705. /// </listheader>
  706. ///
  707. /// <item>
  708. /// <term>ZipProgressEventType.Extracting_BeforeExtractAll</term>
  709. /// <description>
  710. /// Set when ExtractAll() begins. The ArchiveName, Overwrite, and
  711. /// ExtractLocation properties are meaningful.</description>
  712. /// </item>
  713. ///
  714. /// <item>
  715. /// <term>ZipProgressEventType.Extracting_AfterExtractAll</term>
  716. /// <description>
  717. /// Set when ExtractAll() has completed. The ArchiveName, Overwrite,
  718. /// and ExtractLocation properties are meaningful.
  719. /// </description>
  720. /// </item>
  721. ///
  722. /// <item>
  723. /// <term>ZipProgressEventType.Extracting_BeforeExtractEntry</term>
  724. /// <description>
  725. /// Set when an Extract() on an entry in the ZipFile has begun.
  726. /// Properties that are meaningful: ArchiveName, EntriesTotal,
  727. /// CurrentEntry, Overwrite, ExtractLocation, EntriesExtracted.
  728. /// </description>
  729. /// </item>
  730. ///
  731. /// <item>
  732. /// <term>ZipProgressEventType.Extracting_AfterExtractEntry</term>
  733. /// <description>
  734. /// Set when an Extract() on an entry in the ZipFile has completed.
  735. /// Properties that are meaningful: ArchiveName, EntriesTotal,
  736. /// CurrentEntry, Overwrite, ExtractLocation, EntriesExtracted.
  737. /// </description>
  738. /// </item>
  739. ///
  740. /// <item>
  741. /// <term>ZipProgressEventType.Extracting_EntryBytesWritten</term>
  742. /// <description>
  743. /// Set within a call to Extract() on an entry in the ZipFile, as data
  744. /// is extracted for the entry. Properties that are meaningful:
  745. /// ArchiveName, CurrentEntry, BytesTransferred, TotalBytesToTransfer.
  746. /// </description>
  747. /// </item>
  748. ///
  749. /// <item>
  750. /// <term>ZipProgressEventType.Extracting_ExtractEntryWouldOverwrite</term>
  751. /// <description>
  752. /// Set within a call to Extract() on an entry in the ZipFile, when the
  753. /// extraction would overwrite an existing file. This event type is used
  754. /// only when <c>ExtractExistingFileAction</c> on the <c>ZipFile</c> or
  755. /// <c>ZipEntry</c> is set to <c>InvokeExtractProgressEvent</c>.
  756. /// </description>
  757. /// </item>
  758. ///
  759. /// </list>
  760. ///
  761. /// </remarks>
  762. ///
  763. /// <example>
  764. /// <code>
  765. /// private static bool justHadByteUpdate = false;
  766. /// public static void ExtractProgress(object sender, ExtractProgressEventArgs e)
  767. /// {
  768. /// if(e.EventType == ZipProgressEventType.Extracting_EntryBytesWritten)
  769. /// {
  770. /// if (justHadByteUpdate)
  771. /// Console.SetCursorPosition(0, Console.CursorTop);
  772. ///
  773. /// Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, e.TotalBytesToTransfer,
  774. /// e.BytesTransferred / (0.01 * e.TotalBytesToTransfer ));
  775. /// justHadByteUpdate = true;
  776. /// }
  777. /// else if(e.EventType == ZipProgressEventType.Extracting_BeforeExtractEntry)
  778. /// {
  779. /// if (justHadByteUpdate)
  780. /// Console.WriteLine();
  781. /// Console.WriteLine("Extracting: {0}", e.CurrentEntry.FileName);
  782. /// justHadByteUpdate= false;
  783. /// }
  784. /// }
  785. ///
  786. /// public static ExtractZip(string zipToExtract, string directory)
  787. /// {
  788. /// string TargetDirectory= "extract";
  789. /// using (var zip = ZipFile.Read(zipToExtract)) {
  790. /// zip.ExtractProgress += ExtractProgress;
  791. /// foreach (var e in zip1)
  792. /// {
  793. /// e.Extract(TargetDirectory, true);
  794. /// }
  795. /// }
  796. /// }
  797. ///
  798. /// </code>
  799. /// <code lang="VB">
  800. /// Public Shared Sub Main(ByVal args As String())
  801. /// Dim ZipToUnpack As String = "C1P3SML.zip"
  802. /// Dim TargetDir As String = "ExtractTest_Extract"
  803. /// Console.WriteLine("Extracting file {0} to {1}", ZipToUnpack, TargetDir)
  804. /// Using zip1 As ZipFile = ZipFile.Read(ZipToUnpack)
  805. /// AddHandler zip1.ExtractProgress, AddressOf MyExtractProgress
  806. /// Dim e As ZipEntry
  807. /// For Each e In zip1
  808. /// e.Extract(TargetDir, True)
  809. /// Next
  810. /// End Using
  811. /// End Sub
  812. ///
  813. /// Private Shared justHadByteUpdate As Boolean = False
  814. ///
  815. /// Public Shared Sub MyExtractProgress(ByVal sender As Object, ByVal e As ExtractProgressEventArgs)
  816. /// If (e.EventType = ZipProgressEventType.Extracting_EntryBytesWritten) Then
  817. /// If ExtractTest.justHadByteUpdate Then
  818. /// Console.SetCursorPosition(0, Console.CursorTop)
  819. /// End If
  820. /// Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, e.TotalBytesToTransfer, (CDbl(e.BytesTransferred) / (0.01 * e.TotalBytesToTransfer)))
  821. /// ExtractTest.justHadByteUpdate = True
  822. /// ElseIf (e.EventType = ZipProgressEventType.Extracting_BeforeExtractEntry) Then
  823. /// If ExtractTest.justHadByteUpdate Then
  824. /// Console.WriteLine
  825. /// End If
  826. /// Console.WriteLine("Extracting: {0}", e.CurrentEntry.FileName)
  827. /// ExtractTest.justHadByteUpdate = False
  828. /// End If
  829. /// End Sub
  830. /// </code>
  831. /// </example>
  832. ///
  833. /// <seealso cref="Ionic.Zip.ZipFile.SaveProgress"/>
  834. /// <seealso cref="Ionic.Zip.ZipFile.ReadProgress"/>
  835. /// <seealso cref="Ionic.Zip.ZipFile.AddProgress"/>
  836. public event EventHandler<ExtractProgressEventArgs> ExtractProgress;
  837. private void OnExtractEntry(int current, bool before, ZipEntry currentEntry, string path)
  838. {
  839. EventHandler<ExtractProgressEventArgs> ep = ExtractProgress;
  840. if (ep != null)
  841. {
  842. var e = new ExtractProgressEventArgs(ArchiveNameForEvent, before, _entries.Count, current, currentEntry, path);
  843. ep(this, e);
  844. if (e.Cancel)
  845. _extractOperationCanceled = true;
  846. }
  847. }
  848. // Can be called from within ZipEntry._ExtractOne.
  849. internal bool OnExtractBlock(ZipEntry entry, Int64 bytesWritten, Int64 totalBytesToWrite)
  850. {
  851. EventHandler<ExtractProgressEventArgs> ep = ExtractProgress;
  852. if (ep != null)
  853. {
  854. var e = ExtractProgressEventArgs.ByteUpdate(ArchiveNameForEvent, entry,
  855. bytesWritten, totalBytesToWrite);
  856. ep(this, e);
  857. if (e.Cancel)
  858. _extractOperationCanceled = true;
  859. }
  860. return _extractOperationCanceled;
  861. }
  862. // Can be called from within ZipEntry.InternalExtract.
  863. internal bool OnSingleEntryExtract(ZipEntry entry, string path, bool before)
  864. {
  865. EventHandler<ExtractProgressEventArgs> ep = ExtractProgress;
  866. if (ep != null)
  867. {
  868. var e = (before)
  869. ? ExtractProgressEventArgs.BeforeExtractEntry(ArchiveNameForEvent, entry, path)
  870. : ExtractProgressEventArgs.AfterExtractEntry(ArchiveNameForEvent, entry, path);
  871. ep(this, e);
  872. if (e.Cancel)
  873. _extractOperationCanceled = true;
  874. }
  875. return _extractOperationCanceled;
  876. }
  877. internal bool OnExtractExisting(ZipEntry entry, string path)
  878. {
  879. EventHandler<ExtractProgressEventArgs> ep = ExtractProgress;
  880. if (ep != null)
  881. {
  882. var e = ExtractProgressEventArgs.ExtractExisting(ArchiveNameForEvent, entry, path);
  883. ep(this, e);
  884. if (e.Cancel)
  885. _extractOperationCanceled = true;
  886. }
  887. return _extractOperationCanceled;
  888. }
  889. private void OnExtractAllCompleted(string path)
  890. {
  891. EventHandler<ExtractProgressEventArgs> ep = ExtractProgress;
  892. if (ep != null)
  893. {
  894. var e = ExtractProgressEventArgs.ExtractAllCompleted(ArchiveNameForEvent,
  895. path );
  896. ep(this, e);
  897. }
  898. }
  899. private void OnExtractAllStarted(string path)
  900. {
  901. EventHandler<ExtractProgressEventArgs> ep = ExtractProgress;
  902. if (ep != null)
  903. {
  904. var e = ExtractProgressEventArgs.ExtractAllStarted(ArchiveNameForEvent,
  905. path );
  906. ep(this, e);
  907. }
  908. }
  909. #endregion
  910. #region Add
  911. /// <summary>
  912. /// An event handler invoked before, during, and after Adding entries to a zip archive.
  913. /// </summary>
  914. ///
  915. /// <remarks>
  916. /// Adding a large number of entries to a zip file can take a long
  917. /// time. For example, when calling <see cref="AddDirectory(string)"/> on a
  918. /// directory that contains 50,000 files, it could take 3 minutes or so.
  919. /// This event handler allws an application to track the progress of the Add
  920. /// operation, and to optionally cancel a lengthy Add operation.
  921. /// </remarks>
  922. ///
  923. /// <example>
  924. /// <code lang="C#">
  925. ///
  926. /// int _numEntriesToAdd= 0;
  927. /// int _numEntriesAdded= 0;
  928. /// void AddProgressHandler(object sender, AddProgressEventArgs e)
  929. /// {
  930. /// switch (e.EventType)
  931. /// {
  932. /// case ZipProgressEventType.Adding_Started:
  933. /// Console.WriteLine("Adding files to the zip...");
  934. /// break;
  935. /// case ZipProgressEventType.Adding_AfterAddEntry:
  936. /// _numEntriesAdded++;
  937. /// Console.WriteLine(String.Format("Adding file {0}/{1} :: {2}",
  938. /// _numEntriesAdded, _numEntriesToAdd, e.CurrentEntry.FileName));
  939. /// break;
  940. /// case ZipProgressEventType.Adding_Completed:
  941. /// Console.WriteLine("Added all files");
  942. /// break;
  943. /// }
  944. /// }
  945. ///
  946. /// void CreateTheZip()
  947. /// {
  948. /// using (ZipFile zip = new ZipFile())
  949. /// {
  950. /// zip.AddProgress += AddProgressHandler;
  951. /// zip.AddDirectory(System.IO.Path.GetFileName(DirToZip));
  952. /// zip.Save(ZipFileToCreate);
  953. /// }
  954. /// }
  955. ///
  956. /// </code>
  957. ///
  958. /// <code lang="VB">
  959. ///
  960. /// Private Sub AddProgressHandler(ByVal sender As Object, ByVal e As AddProgressEventArgs)
  961. /// Select Case e.EventType
  962. /// Case ZipProgressEventType.Adding_Started
  963. /// Console.WriteLine("Adding files to the zip...")
  964. /// Exit Select
  965. /// Case ZipProgressEventType.Adding_AfterAddEntry
  966. /// Console.WriteLine(String.Format("Adding file {0}", e.CurrentEntry.FileName))
  967. /// Exit Select
  968. /// Case ZipProgressEventType.Adding_Completed
  969. /// Console.WriteLine("Added all files")
  970. /// Exit Select
  971. /// End Select
  972. /// End Sub
  973. ///
  974. /// Sub CreateTheZip()
  975. /// Using zip as ZipFile = New ZipFile
  976. /// AddHandler zip.AddProgress, AddressOf AddProgressHandler
  977. /// zip.AddDirectory(System.IO.Path.GetFileName(DirToZip))
  978. /// zip.Save(ZipFileToCreate);
  979. /// End Using
  980. /// End Sub
  981. ///
  982. /// </code>
  983. ///
  984. /// </example>
  985. ///
  986. /// <seealso cref="Ionic.Zip.ZipFile.SaveProgress"/>
  987. /// <seealso cref="Ionic.Zip.ZipFile.ReadProgress"/>
  988. /// <seealso cref="Ionic.Zip.ZipFile.ExtractProgress"/>
  989. public event EventHandler<AddProgressEventArgs> AddProgress;
  990. private void OnAddStarted()
  991. {
  992. EventHandler<AddProgressEventArgs> ap = AddProgress;
  993. if (ap != null)
  994. {
  995. var e = AddProgressEventArgs.Started(ArchiveNameForEvent);
  996. ap(this, e);
  997. if (e.Cancel) // workitem 13371
  998. _addOperationCanceled = true;
  999. }
  1000. }
  1001. private void OnAddCompleted()
  1002. {
  1003. EventHandler<AddProgressEventArgs> ap = AddProgress;
  1004. if (ap != null)
  1005. {
  1006. var e = AddProgressEventArgs.Completed(ArchiveNameForEvent);
  1007. ap(this, e);
  1008. }
  1009. }
  1010. internal void AfterAddEntry(ZipEntry entry)
  1011. {
  1012. EventHandler<AddProgressEventArgs> ap = AddProgress;
  1013. if (ap != null)
  1014. {
  1015. var e = AddProgressEventArgs.AfterEntry(ArchiveNameForEvent, entry, _entries.Count);
  1016. ap(this, e);
  1017. if (e.Cancel) // workitem 13371
  1018. _addOperationCanceled = true;
  1019. }
  1020. }
  1021. #endregion
  1022. #region Error
  1023. /// <summary>
  1024. /// An event that is raised when an error occurs during open or read of files
  1025. /// while saving a zip archive.
  1026. /// </summary>
  1027. ///
  1028. /// <remarks>
  1029. /// <para>
  1030. /// Errors can occur as a file is being saved to the zip archive. For
  1031. /// example, the File.Open may fail, or a File.Read may fail, because of
  1032. /// lock conflicts or other reasons. If you add a handler to this event,
  1033. /// you can handle such errors in your own code. If you don't add a
  1034. /// handler, the library will throw an exception if it encounters an I/O
  1035. /// error during a call to <c>Save()</c>.
  1036. /// </para>
  1037. ///
  1038. /// <para>
  1039. /// Setting a handler implicitly sets <see cref="ZipFile.ZipErrorAction"/> to
  1040. /// <c>ZipErrorAction.InvokeErrorEvent</c>.
  1041. /// </para>
  1042. ///
  1043. /// <para>
  1044. /// The handler you add applies to all <see cref="ZipEntry"/> items that are
  1045. /// subsequently added to the <c>ZipFile</c> instance. If you set this
  1046. /// property after you have added items to the <c>ZipFile</c>, but before you
  1047. /// have called <c>Save()</c>, errors that occur while saving those items
  1048. /// will not cause the error handler to be invoked.
  1049. /// </para>
  1050. ///
  1051. /// <para>
  1052. /// If you want to handle any errors that occur with any entry in the zip
  1053. /// file using the same error handler, then add your error handler once,
  1054. /// before adding any entries to the zip archive.
  1055. /// </para>
  1056. ///
  1057. /// <para>
  1058. /// In the error handler method, you need to set the <see
  1059. /// cref="ZipEntry.ZipErrorAction"/> property on the
  1060. /// <c>ZipErrorEventArgs.CurrentEntry</c>. This communicates back to
  1061. /// DotNetZip what you would like to do with this particular error. Within
  1062. /// an error handler, if you set the <c>ZipEntry.ZipErrorAction</c> property
  1063. /// on the <c>ZipEntry</c> to <c>ZipErrorAction.InvokeErrorEvent</c> or if
  1064. /// you don't set it at all, the library will throw the exception. (It is the
  1065. /// same as if you had set the <c>ZipEntry.ZipErrorAction</c> property on the
  1066. /// <c>ZipEntry</c> to <c>ZipErrorAction.Throw</c>.) If you set the
  1067. /// <c>ZipErrorEventArgs.Cancel</c> to true, the entire <c>Save()</c> will be
  1068. /// canceled.
  1069. /// </para>
  1070. ///
  1071. /// <para>
  1072. /// In the case that you use <c>ZipErrorAction.Skip</c>, implying that
  1073. /// you want to skip the entry for which there's been an error, DotNetZip
  1074. /// tries to seek backwards in the output stream, and truncate all bytes
  1075. /// written on behalf of that particular entry. This works only if the
  1076. /// output stream is seekable. It will not work, for example, when using
  1077. /// ASPNET's Response.OutputStream.
  1078. /// </para>
  1079. ///
  1080. /// </remarks>
  1081. ///
  1082. /// <example>
  1083. ///
  1084. /// This example shows how to use an event handler to handle
  1085. /// errors during save of the zip file.
  1086. /// <code lang="C#">
  1087. ///
  1088. /// public static void MyZipError(object sender, ZipErrorEventArgs e)
  1089. /// {
  1090. /// Console.WriteLine("Error saving {0}...", e.FileName);
  1091. /// Console.WriteLine(" Exception: {0}", e.exception);
  1092. /// ZipEntry entry = e.CurrentEntry;
  1093. /// string response = null;
  1094. /// // Ask the user whether he wants to skip this error or not
  1095. /// do
  1096. /// {
  1097. /// Console.Write("Retry, Skip, Throw, or Cancel ? (R/S/T/C) ");
  1098. /// response = Console.ReadLine();
  1099. /// Console.WriteLine();
  1100. ///
  1101. /// } while (response != null &amp;&amp;
  1102. /// response[0]!='S' &amp;&amp; response[0]!='s' &amp;&amp;
  1103. /// response[0]!='R' &amp;&amp; response[0]!='r' &amp;&amp;
  1104. /// response[0]!='T' &amp;&amp; response[0]!='t' &amp;&amp;
  1105. /// response[0]!='C' &amp;&amp; response[0]!='c');
  1106. ///
  1107. /// e.Cancel = (response[0]=='C' || response[0]=='c');
  1108. ///
  1109. /// if (response[0]=='S' || response[0]=='s')
  1110. /// entry.ZipErrorAction = ZipErrorAction.Skip;
  1111. /// else if (response[0]=='R' || response[0]=='r')
  1112. /// entry.ZipErrorAction = ZipErrorAction.Retry;
  1113. /// else if (response[0]=='T' || response[0]=='t')
  1114. /// entry.ZipErrorAction = ZipErrorAction.Throw;
  1115. /// }
  1116. ///
  1117. /// public void SaveTheFile()
  1118. /// {
  1119. /// string directoryToZip = "fodder";
  1120. /// string directoryInArchive = "files";
  1121. /// string zipFileToCreate = "Archive.zip";
  1122. /// using (var zip = new ZipFile())
  1123. /// {
  1124. /// // set the event handler before adding any entries
  1125. /// zip.ZipError += MyZipError;
  1126. /// zip.AddDirectory(directoryToZip, directoryInArchive);
  1127. /// zip.Save(zipFileToCreate);
  1128. /// }
  1129. /// }
  1130. /// </code>
  1131. ///
  1132. /// <code lang="VB">
  1133. /// Private Sub MyZipError(ByVal sender As Object, ByVal e As Ionic.Zip.ZipErrorEventArgs)
  1134. /// ' At this point, the application could prompt the user for an action to take.
  1135. /// ' But in this case, this application will simply automatically skip the file, in case of error.
  1136. /// Console.WriteLine("Zip Error, entry {0}", e.CurrentEntry.FileName)
  1137. /// Console.WriteLine(" Exception: {0}", e.exception)
  1138. /// ' set the desired ZipErrorAction on the CurrentEntry to communicate that to DotNetZip
  1139. /// e.CurrentEntry.ZipErrorAction = Zip.ZipErrorAction.Skip
  1140. /// End Sub
  1141. ///
  1142. /// Public Sub SaveTheFile()
  1143. /// Dim directoryToZip As String = "fodder"
  1144. /// Dim directoryInArchive As String = "files"
  1145. /// Dim zipFileToCreate as String = "Archive.zip"
  1146. /// Using zipArchive As ZipFile = New ZipFile
  1147. /// ' set the event handler before adding any entries
  1148. /// AddHandler zipArchive.ZipError, AddressOf MyZipError
  1149. /// zipArchive.AddDirectory(directoryToZip, directoryInArchive)
  1150. /// zipArchive.Save(zipFileToCreate)
  1151. /// End Using
  1152. /// End Sub
  1153. ///
  1154. /// </code>
  1155. /// </example>
  1156. ///
  1157. /// <seealso cref="Ionic.Zip.ZipFile.ZipErrorAction"/>
  1158. public event EventHandler<ZipErrorEventArgs> ZipError;
  1159. internal bool OnZipErrorSaving(ZipEntry entry, Exception exc)
  1160. {
  1161. if (ZipError != null)
  1162. {
  1163. lock (LOCK)
  1164. {
  1165. var e = ZipErrorEventArgs.Saving(this.Name, entry, exc);
  1166. ZipError(this, e);
  1167. if (e.Cancel)
  1168. _saveOperationCanceled = true;
  1169. }
  1170. }
  1171. return _saveOperationCanceled;
  1172. }
  1173. #endregion
  1174. }
  1175. }