Track 7-Zip Extraction Progress Programmatically

Tracking the extraction progress programmatically using the 7-Zip SDK is accomplished by implementing the IArchiveExtractCallback interface, which inherits from IProgress. By providing a custom implementation of this callback to the IInArchive::Extract method, developers receive real-time notifications regarding the total byte size, the number of bytes currently processed, and the status of individual files during the decompression process.

The Core Progress Tracking Methods

The primary mechanism for byte-level progress reporting resides within the IProgress base interface:

  • SetTotal(UInt64 total): The extraction engine calls this method once it calculates the total uncompressed or compressed size of the files being extracted. This value serves as the denominator for percentage calculations.
  • SetCompleted(const UInt64 *completeValue): The engine invokes this method periodically throughout the extraction process. The pointer completeValue provides the current number of bytes processed so far. If completeValue is null, the total progress state is indeterminate.

Calculating the percentage completed is done using the standard formula:

\[\text{Percentage} = \left( \frac{\text{completeValue}}{\text{total}} \right) \times 100\]

File-Level Status Callbacks

In addition to byte counters, the IArchiveExtractCallback interface provides granular hooks for individual archive entries:

  • GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode): Called before extracting an item. It supplies the archive item's index and requests an output stream where decompressed data should be written.
  • PrepareOperation(Int32 askExtractMode): Notifies the application about the planned action (e.g., extract, test, or skip).
  • SetOperationResult(Int32 resultOperationOK): Signals the completion of an individual file's extraction and reports whether it succeeded, failed with a CRC error, or encountered data corruption.

Implementation Workflow

To track extraction progress, follow these sequential steps:

  1. Define a Custom Callback Class: Create a class (e.g., CExtractCallback) that inherits from IArchiveExtractCallback (and internally IProgress).
  2. Implement SetTotal and SetCompleted: Store the total size and update your user interface or progress log whenever SetCompleted passes a new value.
  3. Instantiate the Callback: Create an instance of your custom class.
  4. Call Extract: Pass a pointer to your callback instance into the archive object's extraction function:
CMyExtractCallback *extractCallbackSpec = new CMyExtractCallback;
CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;

// indices: array of item indices to extract, NULL for all items
// numItems: count of items to extract, -1 for all items
// testMode: 0 for extract, 1 for test
archive->Extract(NULL, (UInt32)(Int32)-1, 0, extractCallback);

By returning S_OK from each callback invocation, extraction proceeds normally. Returning E_ABORT from SetCompleted or any other callback method instructs the 7-Zip engine to halt extraction immediately, providing built-in cancellation support.