diff --git a/SevenZip/ArchiveExtractCallback.cs b/SevenZip/ArchiveExtractCallback.cs index 00a4628..5ccc8d5 100644 --- a/SevenZip/ArchiveExtractCallback.cs +++ b/SevenZip/ArchiveExtractCallback.cs @@ -1,5 +1,6 @@ namespace SevenZip { + using SevenZip.EventArguments; using System; using System.Collections.Generic; using System.Globalization; @@ -157,6 +158,11 @@ private void CommonInit(IInArchive archive, int filesCount, SevenZipExtractor ex /// public event EventHandler Extracting; + /// + /// Occurs when 7z library has made progress on an operation + /// + public event EventHandler Progressing; + /// /// Occurs during the extraction when a file already exists /// @@ -202,6 +208,14 @@ private void OnExtracting(ProgressEventArgs e) } } + private void OnProgressing(DetailedProgressEventArgs e) + { + if (Progressing != null) + { + Progressing(this, e); + } + } + private void IntEventArgsHandler(object sender, IntEventArgs e) { // If _bytesCount is not set, we can't update the progress. @@ -240,7 +254,14 @@ public void SetTotal(ulong total) OnOpen(new OpenEventArgs(total)); } - public void SetCompleted(ref ulong completeValue) { } + /// + /// Sets the amount of work that has been completed. + /// + /// Amount of work that has been completed (in bytes) + public void SetCompleted(ref ulong completeValue) + { + OnProgressing(new DetailedProgressEventArgs(completeValue, (ulong)_bytesCount)); + } /// /// Sets output stream for writing unpacked data @@ -292,7 +313,7 @@ public int GetStream(uint index, out ISequentialOutStream outStream, AskMode ask } #endregion - + try { fileName = Path.Combine(RemoveIllegalCharacters(_directory, true), RemoveIllegalCharacters(_directoryStructure ? entryName : Path.GetFileName(entryName))); @@ -452,7 +473,7 @@ public void SetOperationResult(OperationResult operationResult) case OperationResult.UnexpectedEnd: AddException(new ExtractionFailedException("Unexpected end of file.")); break; - case OperationResult.DataAfterEnd: + case OperationResult.DataAfterEnd: AddException(new ExtractionFailedException("Data after end of archive.")); break; case OperationResult.IsNotArc: @@ -482,7 +503,7 @@ public void SetOperationResult(OperationResult operationResult) _fileStream = null; } var iea = new FileInfoEventArgs( - _extractor.ArchiveFileData[_currentIndex], PercentDoneEventArgs.ProducePercentDone(_doneRate)); + _extractor.ArchiveFileData[_currentIndex], PercentDoneEventArgs.ProducePercentDone(_doneRate)); OnFileExtractionFinished(iea); if (iea.Cancel) { diff --git a/SevenZip/ArchiveUpdateCallback.cs b/SevenZip/ArchiveUpdateCallback.cs index 5c180b7..52510ce 100644 --- a/SevenZip/ArchiveUpdateCallback.cs +++ b/SevenZip/ArchiveUpdateCallback.cs @@ -1,5 +1,6 @@ namespace SevenZip { + using SevenZip.EventArguments; using System; using System.Collections.Generic; using System.IO; @@ -73,7 +74,7 @@ internal sealed class ArchiveUpdateCallback : CallbackBase, IArchiveUpdateCallba /// /// Gets or sets the value indicating whether to compress as fast as possible, without calling events. /// - public bool FastCompression { private get; set; } + public bool FastCompression { private get; set; } private int _memoryPressure; @@ -183,7 +184,7 @@ private void CommonInit(SevenZipCompressor compressor, UpdateData updateData, bo } _updateData = updateData; _directoryStructure = directoryStructure; - DefaultItemName = "default"; + DefaultItemName = "default"; } private void Init( @@ -282,7 +283,7 @@ private bool EventsForGetStream(uint index) _fileStream.BytesRead += IntEventArgsHandler; } _doneRate += 1.0f / _actualFilesCount; - var fiea = new FileNameEventArgs(_files != null? _files[index].Name : _entries[index], + var fiea = new FileNameEventArgs(_files != null ? _files[index].Name : _entries[index], PercentDoneEventArgs.ProducePercentDone(_doneRate)); OnFileCompression(fiea); if (fiea.Cancel) @@ -307,6 +308,11 @@ private bool EventsForGetStream(uint index) /// public event EventHandler Compressing; + /// + /// Occurs when 7z library has made progress on an operation + /// + public event EventHandler Progressing; + /// /// Occurs when the current file was compressed. /// @@ -327,6 +333,13 @@ private void OnCompressing(ProgressEventArgs e) Compressing(this, e); } } + private void OnProgressing(DetailedProgressEventArgs e) + { + if (Progressing != null) + { + Progressing(this, e); + } + } private void OnFileCompressionFinished(EventArgs e) { @@ -340,9 +353,25 @@ private void OnFileCompressionFinished(EventArgs e) #region IArchiveUpdateCallback Members - public void SetTotal(ulong total) {} + private ulong _total; + /// + /// Gives the total size of data that will be compressed + /// + /// Amount of data to compress (in bytes) + public void SetTotal(ulong total) + { + _total = total; + } - public void SetCompleted(ref ulong completeValue) {} + + /// + /// Sets the amount of work that has been completed. + /// + /// Amount of work that has been completed (in bytes) + public void SetCompleted(ref ulong completeValue) + { + OnProgressing(new DetailedProgressEventArgs(completeValue, (ulong)_bytesCount)); + } public int GetUpdateItemInfo(uint index, ref int newData, ref int newProperties, ref uint indexInArchive) { @@ -442,7 +471,7 @@ public int GetProperty(uint index, ItemPropId propID, ref PropVariant value) } else { - val = _updateData.FileNamesToModify[(int) index]; + val = _updateData.FileNamesToModify[(int)index]; } value.Value = Marshal.StringToBSTR(val); #endregion @@ -469,7 +498,7 @@ public int GetProperty(uint index, ItemPropId propID, ref PropVariant value) } else { - value.UInt64Value = Convert.ToUInt64(_updateData.ArchiveFileData[(int) index].IsDirectory); + value.UInt64Value = Convert.ToUInt64(_updateData.ArchiveFileData[(int)index].IsDirectory); } break; case ItemPropId.Size: @@ -483,23 +512,23 @@ public int GetProperty(uint index, ItemPropId propID, ref PropVariant value) { if (_streams == null) { - size = _bytesCount > 0 ? (ulong) _bytesCount : 0; + size = _bytesCount > 0 ? (ulong)_bytesCount : 0; } else { - size = (ulong) (_streams[index] == null? 0 : _streams[index].Length); + size = (ulong)(_streams[index] == null ? 0 : _streams[index].Length); } } else { size = (_files[index].Attributes & FileAttributes.Directory) == 0 - ? (ulong) _files[index].Length + ? (ulong)_files[index].Length : 0; } } else { - size = _updateData.ArchiveFileData[(int) index].Size; + size = _updateData.ArchiveFileData[(int)index].Size; } value.UInt64Value = size; @@ -522,12 +551,12 @@ public int GetProperty(uint index, ItemPropId propID, ref PropVariant value) } else { - value.UInt32Value = (uint) _files[index].Attributes; + value.UInt32Value = (uint)_files[index].Attributes; } } else { - value.UInt32Value = _updateData.ArchiveFileData[(int) index].Attributes; + value.UInt32Value = _updateData.ArchiveFileData[(int)index].Attributes; } break; #region Times @@ -541,7 +570,7 @@ public int GetProperty(uint index, ItemPropId propID, ref PropVariant value) } else { - value.Int64Value = _updateData.ArchiveFileData[(int) index].CreationTime.ToFileTime(); + value.Int64Value = _updateData.ArchiveFileData[(int)index].CreationTime.ToFileTime(); } break; case ItemPropId.LastAccessTime: @@ -554,7 +583,7 @@ public int GetProperty(uint index, ItemPropId propID, ref PropVariant value) } else { - value.Int64Value = _updateData.ArchiveFileData[(int) index].LastAccessTime.ToFileTime(); + value.Int64Value = _updateData.ArchiveFileData[(int)index].LastAccessTime.ToFileTime(); } break; case ItemPropId.LastWriteTime: @@ -567,7 +596,7 @@ public int GetProperty(uint index, ItemPropId propID, ref PropVariant value) } else { - value.Int64Value = _updateData.ArchiveFileData[(int) index].LastWriteTime.ToFileTime(); + value.Int64Value = _updateData.ArchiveFileData[(int)index].LastWriteTime.ToFileTime(); } break; #endregion @@ -593,7 +622,7 @@ public int GetProperty(uint index, ItemPropId propID, ref PropVariant value) } else { - val = Path.GetExtension(_updateData.ArchiveFileData[(int) index].FileName); + val = Path.GetExtension(_updateData.ArchiveFileData[(int)index].FileName); value.Value = Marshal.StringToBSTR(val); } @@ -692,7 +721,7 @@ public void SetOperationResult(OperationResult operationResult) case OperationResult.UnexpectedEnd: AddException(new ExtractionFailedException("Unexpected end of file.")); break; - case OperationResult.DataAfterEnd: + case OperationResult.DataAfterEnd: AddException(new ExtractionFailedException("Data after end of archive.")); break; case OperationResult.IsNotArc: @@ -711,21 +740,21 @@ public void SetOperationResult(OperationResult operationResult) } if (_fileStream != null) { - - _fileStream.BytesRead -= IntEventArgsHandler; - //Specific Zip implementation - can not Dispose files for Zip. - if (_compressor.ArchiveFormat != OutArchiveFormat.Zip) + + _fileStream.BytesRead -= IntEventArgsHandler; + //Specific Zip implementation - can not Dispose files for Zip. + if (_compressor.ArchiveFormat != OutArchiveFormat.Zip) + { + try { - try - { - _fileStream.Dispose(); - } - catch (ObjectDisposedException) {} + _fileStream.Dispose(); } - else - { - _wrappersToDispose.Add(_fileStream); - } + catch (ObjectDisposedException) { } + } + else + { + _wrappersToDispose.Add(_fileStream); + } _fileStream = null; } OnFileCompressionFinished(EventArgs.Empty); @@ -756,7 +785,7 @@ public void Dispose() { _fileStream.Dispose(); } - catch (ObjectDisposedException) {} + catch (ObjectDisposedException) { } } if (_wrappersToDispose != null) @@ -767,7 +796,7 @@ public void Dispose() { wrapper.Dispose(); } - catch (ObjectDisposedException) {} + catch (ObjectDisposedException) { } } } @@ -778,11 +807,11 @@ public void Dispose() private void IntEventArgsHandler(object sender, IntEventArgs e) { - var lockObject = ((object) _files ?? _streams) ?? _fileStream; + var lockObject = ((object)_files ?? _streams) ?? _fileStream; lock (lockObject) { - var pold = (byte) (_bytesWrittenOld*100/_bytesCount); + var pold = (byte)(_bytesWrittenOld * 100 / _bytesCount); _bytesWritten += e.Value; byte pnow; @@ -798,7 +827,7 @@ private void IntEventArgsHandler(object sender, IntEventArgs e) if (pnow > pold) { _bytesWrittenOld = _bytesWritten; - OnCompressing(new ProgressEventArgs(pnow, (byte) (pnow - pold))); + OnCompressing(new ProgressEventArgs(pnow, (byte)(pnow - pold))); } } } diff --git a/SevenZip/EventArguments/DetailedProgressEventArgs.cs b/SevenZip/EventArguments/DetailedProgressEventArgs.cs new file mode 100644 index 0000000..d1c632b --- /dev/null +++ b/SevenZip/EventArguments/DetailedProgressEventArgs.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace SevenZip.EventArguments +{ + /// + /// Event args that pass a ulong total and a ulong completed value, that can be interpreted by the receiver. + /// + public sealed class DetailedProgressEventArgs : EventArgs + { + private readonly ulong _amountedCompleted; + private readonly ulong _total; + + /// + /// Initializes a new instance of the DetailedProgressEventArgs class. + /// + /// Amount of work that has been cumulatively completed. + /// The total amount of work to complete. + /// + public DetailedProgressEventArgs(ulong amountCompleted, ulong total) + { + if (amountCompleted < 0 || amountCompleted > total) + { + throw new ArgumentOutOfRangeException("amountCompleted", + "The amount of completed work (" + amountCompleted + ") must be less than the total (" + total + ")."); + } + + _amountedCompleted = amountCompleted; + _total = total; + } + + /// + /// Gets the amount of work that has been completed. + /// + public ulong AmountCompleted => _amountedCompleted; + /// + /// Gets the total amount of work to do. + /// + public ulong TotalAmount => _total; + } +} diff --git a/SevenZip/SevenZipCompressor.cs b/SevenZip/SevenZipCompressor.cs index 1e18100..c61a12b 100644 --- a/SevenZip/SevenZipCompressor.cs +++ b/SevenZip/SevenZipCompressor.cs @@ -7,7 +7,7 @@ namespace SevenZip using System.Linq; using System.Runtime.InteropServices; using System.Security.Permissions; - + using SevenZip.EventArguments; using SevenZip.Sdk; using SevenZip.Sdk.Compression.Lzma; @@ -692,6 +692,7 @@ private void CommonUpdateCallbackInit(ArchiveUpdateCallback auc) { auc.FileCompressionStarted += FileCompressionStartedEventProxy; auc.Compressing += CompressingEventProxy; + auc.Progressing += ProgressingEventProxy; auc.FileCompressionFinished += FileCompressionFinishedEventProxy; auc.DefaultItemName = DefaultItemName; auc.FastCompression = FastCompression; @@ -857,6 +858,7 @@ private void FreeCompressionCallback(ArchiveUpdateCallback callback) { callback.FileCompressionStarted -= FileCompressionStartedEventProxy; callback.Compressing -= CompressingEventProxy; + callback.Progressing -= ProgressingEventProxy; callback.FileCompressionFinished -= FileCompressionFinishedEventProxy; } @@ -970,9 +972,16 @@ private ArchiveOpenCallback GetArchiveOpenCallback() /// /// Occurs when data are being compressed /// - /// Use this event for accurate progress handling and various ProgressBar.StepBy(e.PercentDelta) routines + /// Use this event for semi-accurate progress and various ProgressBar.StepBy(e.PercentDelta) routines public event EventHandler Compressing; + /// + /// Occurs when the 7z library indicates work has been done + /// + /// Use this event for your own handling of accurate progress. + public event EventHandler Progressing; + + /// /// Occurs when all files information was determined and SevenZipCompressor is about to start to compress them. /// @@ -1016,6 +1025,16 @@ private void CompressingEventProxy(object sender, ProgressEventArgs e) OnEvent(Compressing, e, false); } + /// + /// Event proxy for Progressing. + /// + /// The sender of the event. + /// The event arguments. + private void ProgressingEventProxy(object sender, DetailedProgressEventArgs e) + { + OnEvent(Progressing, e, false); + } + /// /// Event proxy for FilesFound. /// diff --git a/SevenZip/SevenZipExtractor.cs b/SevenZip/SevenZipExtractor.cs index 41d4a8b..9f5879c 100644 --- a/SevenZip/SevenZipExtractor.cs +++ b/SevenZip/SevenZipExtractor.cs @@ -7,7 +7,7 @@ namespace SevenZip using System.Globalization; using System.IO; using System.Linq; - + using SevenZip.EventArguments; using SevenZip.Sdk.Compression.Lzma; /// @@ -631,6 +631,7 @@ private void ArchiveExtractCallbackCommonInit(ArchiveExtractCallback aec) aec.FileExtractionStarted += FileExtractionStartedEventProxy; aec.FileExtractionFinished += FileExtractionFinishedEventProxy; aec.Extracting += ExtractingEventProxy; + aec.Progressing += ProgressingEventProxy; aec.FileExists += FileExistsEventProxy; } @@ -673,6 +674,7 @@ private void FreeArchiveExtractCallback(ArchiveExtractCallback callback) callback.FileExtractionStarted -= FileExtractionStartedEventProxy; callback.FileExtractionFinished -= FileExtractionFinishedEventProxy; callback.Extracting -= ExtractingEventProxy; + callback.Progressing -= ProgressingEventProxy; callback.FileExists -= FileExistsEventProxy; } #endregion @@ -797,9 +799,16 @@ public void Dispose() /// /// Occurs when data are being extracted. /// - /// Use this event for accurate progress handling and various ProgressBar.StepBy(e.PercentDelta) routines. + /// This event does not seem to be accurate for total progress. public event EventHandler Extracting; + /// + /// Occurs when the 7z library indicates work has been done + /// + /// Use this event for your own handling of progress. It does not implement delta StepBy calls. + public event EventHandler Progressing; + + /// /// Occurs during the extraction when a file already exists. /// @@ -816,6 +825,16 @@ private void FileExtractionStartedEventProxy(object sender, FileInfoEventArgs e) OnEvent(FileExtractionStarted, e, true); } + /// + /// Event proxy for Progressing. + /// + /// The sender of the event. + /// The event arguments. + private void ProgressingEventProxy(object sender, DetailedProgressEventArgs e) + { + OnEvent(Progressing, e, false); + } + /// /// Event proxy for FileExtractionFinished. ///