ISApexEx v0.1 Beta 2
Unified Archive Extraction & Patching API for Inno Setup
7-Zip · FreeArc · RAR · Xdelta3 · HDiffPatch one DLL · Win32 · by BLACKFIRE69
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━
▌ OVERVIEW
ISApexEx is a high-performance unified library crafted for Inno Setup. It integrates
five engines
7-Zip,
FreeArc,
RAR,
Xdelta3, and
HDiffPatch into a single DLL with seamless cross-format progress tracking. Mix and match
.7z, .zip, .arc, .bf, .rar and xdelta3 / HDiff patch operations in one installer with continuous progress across all of them.
▌ TECHNICAL SPECIFICATIONS- Version v0.1 Beta 2
- Author BLACKFIRE69
- Build 6A3DC100
- File Size 305 KB
- Compatibility Inno Setup v6.x or v5.x
Code:
╭──────────┬──────────┬──────────────────────┬─────────────────────────────╮
│ Engine │ Version │ Native DLL │ Supported Extensions │
├──────────┼──────────┼──────────────────────┼─────────────────────────────┤
│ 7-Zip │ v26.10 │ 7z_32.dll │ .7z, .zip, .7z.001/.002... │
│ FreeArc │ v0.67 │ UnArc_32.dll │ .arc, .bf... │
│ UnRAR │ v7.22 │ UnRAR_32.dll │ .rar, .part01.rar... │
│ xdelta3 │ v0.1 │ xdelta3_wrapper.dll │ .xd3, .xdelta, .vcdiff... │
│ HDiff │ v0.1 │ hpatchz_wrapper.dll │ .hdiff... │
╰──────────┴──────────┴──────────────────────┴─────────────────────────────╯
Disk-spanning (FreeArc 'diskspan' volumes setup-1.bin, setup-2.bin
): handled by
cls-diskspan v2.0 (modified edition)
natively no ClsFunc* calls needed from your script.
▌ KEY FEATURES
✦ Unified Multi-Format Support
Handle .7z, .zip, .arc, .bf, .rar and xdelta3 / HDiff patches from one DLL. Format is auto-detected from the file extension no manual engine selection.
✦ Top-Level AND Split / Multi-Volume Support
Every format extracts both as a single top-level archive and as a split set: 7z split volumes (.7z.001
), RAR multi-volume (.partNN.rar / .rNN), FreeArc disk-span volumes. Parts may even be scattered across different folders or discs.
✦ Universal File Browsing (Locate a Missing Archive or Part)
When ISApexEx can't find a file it needs a top-level archive of ANY format, a 7z split part, a RAR volume, or a FreeArc spanned volume it lets the user locate it, then resumes. Built-in native browse dialog, or your own themed dialog via
ISApexExSetDiskRequestCallback (one callback covers every case).
✦ Lazy DLL Loading
Only the native engine DLLs actually needed are loaded at runtime. Using only .7z and .rar? UnArc_32.dll, xdelta3_wrapper.dll and hpatchz_wrapper.dll are never touched.
✦ Cross-Format Progress
Overall progress (01000) spans all registered disks regardless of format. A mixed .arc + .7z + .rar + xdelta3 + .hdiff setup shows one smooth, continuous bar.
✦ Custom Extension Mapping
Archives don't have to use standard extensions map any extension to any engine via
ISApexExRegisterExtension before adding disks.
Code:
ISApexExRegisterExtension('.bin', APEX_ARC_7Z); // .bin -> 7z engine
ISApexExRegisterExtension('.cp', APEX_ARC_ARC); // .cp -> FreeArc engine
ISApexExRegisterExtension('.dat', APEX_ARC_RAR); // .dat -> RAR engine
✦ Advanced Progress Tracking
Real-time Overall Progress, Current Disk Progress, and Extracted/Total File Counts.
✦ Performance Metrics
Accurate Current and Average Speed (MB/s).
✦ Time Management
"Time Remaining" + "Elapsed Time" with three display formats (
00:00:00 /
x hr y min /
x hours y minutes).
✦ Process Control
Suspend, Resume, or Stop the extraction safely at any point.
✦ UI Stability
"Calc Accuracy" reduction logic prevents erratic jumping in speed and ETA displays.
✦ Localization
Switch languages at runtime via external .ini files. Ships with English and Russian.
✦ Event Callback System
Optional callback fires on discrete lifecycle events engine loaded, disk started/finished/failed, error, all done. Great for logging and diagnostics.
✦ File-Based Logging
Thread-safe logging with configurable verbosity (Off, Error, Info, Verbose).
✦ Thread Priority Control
Set extraction thread priority before each disk (Idle
Highest).
✦ Disk Space Pre-Check
Verify free space on the output drive before extraction per-disk or all disks at once.
✦ Progress Persistence / Resume (Crash Recovery)
On a crash (power loss, kill, BSOD) the library has saved state after each disk; on relaunch
ISApexExLoadResume validates and restores progress, already-done disks are skipped. CRC32-checked, auto-deleted on success, fully opt-in (zero overhead unless
ISApexExSetResumeFile is called).
▌ ENGINE FEATURES
◆ 7-Zip
Normal + split archives (.7z.001
), ZIP via the same engine, password-protected archives. The 7-Zip API requires split parts to be merged first, so ISApexEx builds a local temp file. Single directory → auto-detected; parts spread across folders → set the total with
ISApexExSetSplitPartCount; override the temp location with
ISApexExSetSplitTmpPath.
◆ FreeArc
Normal .arc/.bf, selective folder extraction (
ISApexExAddDisksEx), external processor integration (SREP, XTool, LOLZ, NZ, RZ
), config file + work path (
ISApexExExtractEx), password-protected archives, and native disk-span support via cls-diskspan v2.0 when a volume is missing, the user is prompted to locate it and extraction resumes. Ship cls-diskspan.dll next to ISApexEx.dll; no ClsFunc* calls needed.
◆ RAR
Normal + multi-volume archives (.part01.rar
) with automatic volume switching (no extra API calls), password-protected archives.
◆ Xdelta3 Patching- Single-file patching ISApexExAddDeltaPatch(PatchFile, SourceFile, OutputFile)
- Batch directory patching ISApexExAddDeltaPatchDir(PatchDir, SourceDir, OutputDir, Pattern)
- In-place patching when source = output, done via a temp file (decode to .xd3tmp, delete original, rename)
- User-defined patch extensions Pattern controls the scanned extension: *.xd3 (default), *.patch, *.delta, *.myext
- Recursive directory scanning batch mode searches subdirectories (now recursive by default)
- Deferred listing patch/source dirs are scanned at extraction time, so you can patch files produced by an earlier archive in the same installer
- Interleaved workflow extract archives and apply patches in any order; progress stays continuous
◆ HDiffPatch [NEW]- Single-file patching ISApexExAddHDiffPatch(PatchFile, SourceFile, OutputFile) applies a .hdiff binary patch (old + diff → new)
- Batch directory patching ISApexExAddHDiffPatchDir(PatchDir, SourceDir, OutputDir, Pattern), default pattern *.hdiff, recursive (scans subfolders)
- Apply-side only via hpatchz_wrapper.dll, lazy-loaded; ArchiveType APEX_ARC_HDIFF = 4
- Fully interleaved mixes with .7z/.arc/.rar/.xd3 in one session under the same unified progress (01000)
▌ SUPPORTED FILE STRUCTURES
Code:
[ROOT]
├── data1.7z (normal 7z archive)
├── data2.zip (ZIP archive via 7z engine)
├── Disks/
│ ├── Disk1/
│ │ ├── Sonic 2.7z.001 (split 7z, parts across directories)
│ │ └── Sonic 2.7z.002
│ └── Disk2/
│ ├── Sonic 2.7z.003
│ └── Sonic 2.7z.004
├── data3.arc (FreeArc archive)
├── data4.bf (FreeArc archive)
├── data5.part01.rar (multi-volume RAR)
├── data5.part02.rar
├── data5.part03.rar
├── data6.rar (normal RAR archive)
├── setup-1.bin (cls-diskspan archive)
├── data7_xdelta.bin (archive containing xdelta3 patches)
├── data8_hdiff.bin (archive containing .hdiff patches)
└── Setup.exe
▌ SUPPORTED FILE EXTENSIONS
Code:
╭────────────────────────────┬──────────────────┬──────────────────╮
│ Extensions │ Engine │ Constant │
├────────────────────────────┼──────────────────┼──────────────────┤
│ .7z .7z.001 .7z.002 ... │ 7z engine │ APEX_ARC_7Z │
│ .zip │ 7z engine │ APEX_ARC_7Z │
│ .arc .bf │ FreeArc engine │ APEX_ARC_ARC │
│ .rar .r00 .r01 ... │ RAR engine │ APEX_ARC_RAR │
│ .xd3 .xdelta .vcdiff ... │ xdelta3 engine │ APEX_ARC_XDELTA │
│ .hdiff ... │ HDiff engine │ APEX_ARC_HDIFF │
╰────────────────────────────┴──────────────────┴──────────────────╯
▌ EXPORTED API FUNCTIONS- Initialization ISApexExInit, ISApexExInitEx
- Disk Registration ISApexExAddDisks, ISApexExAddDisksEx, ISApexExAddDeltaPatch, ISApexExAddDeltaPatchDir, ISApexExAddHDiffPatch, ISApexExAddHDiffPatchDir, ISApexExRegisterExtension, ISApexExClearExtensions
- Extraction ISApexExExtract, ISApexExExtractEx
- Process Control ISApexExSuspendProc, ISApexExResumeProc, ISApexExIsSuspended, ISApexExStop
- Progress & Metrics ISApexExGetTotalSizeMBOfAllDisks, ISApexExGetExtractedSizeMBOfAllDisks, ISApexExCallbackInterval, ISApexExGetCallbackInterval, ISApexExReduceCalcAccuracy
- Configuration ISApexExChangeLanguage, ISApexExSetSplitPartCount, ISApexExSetSplitTmpPath, ISApexExSetThreadPriority, ISApexExCheckFreeSpace, ISApexExCheckAllFreeSpace
- Logging & Events ISApexExSetLogFile, ISApexExSetLogLevel, ISApexExSetEventCallback
- File Browsing ISApexExSetDiskRequestCallback (global covers every format + missing-part case)
- Resume / Crash Recovery ISApexExSetResumeFile, ISApexExLoadResume, ISApexExHasResume, ISApexExClearResume
▌ QUICK START EXAMPLES
Example 1 Mixed Archives (7z + FreeArc + RAR)
Code:
#include "ISApexEx.iss"
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssInstall then
begin
if not AddArchiveEntry('data1.7z') then Exit;
if not AddArchiveEntry('data2.bf') then Exit;
if not AddArchiveEntry('data3.rar') then Exit;
if ISApexExInitEx(2, @ProgressCallbackEx) then
begin
for i := 1 to ISApexExDiskCount do
if not ISApexExExtract(i) then Break;
ISApexExStop;
end;
end;
end;
Example 2 Extract + xdelta3 Batch Patching
Code:
if not AddArchiveEntry('data1.7z') then Exit; // base archive
if not AddArchiveEntry('data_xdelta.rar') then Exit; // sources + patches
// apply all *.xd3 in \patches to sources in \modified -> \rebuilt (recursive)
ISApexExAddDeltaPatchDir(
ExpandConstant('{app}\patches'),
ExpandConstant('{app}\modified'),
ExpandConstant('{app}\rebuilt'),
'*.xd3');
ISApexExDiskCount := ISApexExDiskCount + 1;
Example 3 Single File xdelta3 Patch (In-Place)
Code:
if not AddArchiveEntry('data1.7z') then Exit; // contains original game.exe
// patch game.exe in-place using game.exe.xd3
ISApexExAddDeltaPatch(
ExpandConstant('{src}\game.exe.xd3'),
ExpandConstant('{app}\game.exe'),
ExpandConstant('{app}\game.exe'));
ISApexExDiskCount := ISApexExDiskCount + 1;
Example 4 Split 7z Archive (Multi-Part .7z.001/.002/
)
Code:
if not AddArchiveEntry('Sonic 2.7z.001') then Exit;
// parts spread across folders: declare total count + a temp path
ISApexExSetSplitPartCount(ISApexExDiskCount, 7);
ISApexExSetSplitTmpPath(ISApexExDiskCount, ExpandConstant('{src}'));
Example 5 Split RAR Archive (Multi-Volume .part01.rar/
)
Code:
if not AddArchiveEntry('data1.7z') then Exit;
// just pass the first part UnRAR switches volumes automatically
if not AddArchiveEntry('data3.part01.rar') then Exit;
Example 6 Progress Persistence / Resume (Crash Recovery)
Code:
ISApexExSetResumeFile(ExpandConstant('{src}\ISApexEx.resume'));
if ISApexExInitEx(2, @ProgressCallbackEx) then
begin
if ISApexExLoadResume then // prompts Yes/No to resume
Log('Resuming from previous session');
for i := 1 to ISApexExDiskCount do // done disks are skipped
if not ISApexExExtractEx(i, cfg, tmp) then Break;
ISApexExStop; // auto-deletes resume file on success
end;
Example 7 Global "Locate Missing Archive / Volume / Part" Dialog
One callback handles EVERY case: a missing top-level archive of any format, a 7z split part, a RAR volume, or a FreeArc spanned volume. Runs on the main thread (MsgBox / GetOpenFileName / a custom TForm are all safe). Omit it to use the built-in native browse.
Code:
function MyDiskRequest(const Filename, CurrentDir: WideString): WideString;
begin
if MsgBox('Please insert / locate: ' + Filename,
mbConfirmation, MB_OKCANCEL) = mrCancel then
begin
Result := ''; // cancel -> clean user-abort
Exit;
end;
// ... GetOpenFileName, or your own themed TForm ...
Result := PickedFolder; // the folder that now holds Filename
end;
// register once, after Init, before Extract:
ISApexExSetDiskRequestCallback(@MyDiskRequest);
Example 8 HDiffPatch (Single-File + Batch) [NEW]
A full runnable version is in bin\ISApexEx_Example_HDiff.iss. Ship hpatchz_wrapper.dll next to the other engine DLLs.
Code:
if not AddArchiveEntry('data1.7z') then Exit; // sources + .hdiff patches
// single file: apply game.exe.hdiff to game.exe in-place
ISApexExAddHDiffPatch(
ExpandConstant('{src}\game.exe.hdiff'),
ExpandConstant('{app}\game.exe'),
ExpandConstant('{app}\game.exe'));
ISApexExDiskCount := ISApexExDiskCount + 1;
// batch: apply all *.hdiff in \patches to \modified -> \rebuilt (recursive)
ISApexExAddHDiffPatchDir(
ExpandConstant('{app}\patches'),
ExpandConstant('{app}\modified'),
ExpandConstant('{app}\rebuilt'),
'*.hdiff');
ISApexExDiskCount := ISApexExDiskCount + 1;
▌ DISTRIBUTION FILES- ISApexEx.dll Unified API library (single DLL for all five engines)
- ISApexEx.iss Header for Inno Setup (types, constants, imports)
- 7z_32.dll 7-Zip engine (.7z/.zip)
- UnArc_32.dll FreeArc engine (.arc/.bf)
- UnRAR_32.dll UnRAR engine (.rar)
- xdelta3_wrapper.dll xdelta3 engine (.xd3 patching)
- hpatchz_wrapper.dll HDiffPatch engine (.hdiff apply)
- cls-diskspan.dll (Optional) FreeArc disk-spanning plugin, v2.0 modified edition. Only for setup-N.bin sets.
- English.ini / Russian.ini Language files
- arc.ini / CLS.ini FreeArc external-processor configuration
Engine DLLs are lazy-loaded ship only the ones the archives you use actually need.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━
Feedback, bug reports, and edge cases are all welcome.
.