Requirements#
I often need to build installation packages, and in this area, nothing beats InnoSetup. I’ve tried many similar systems — NSIS, InstallShield, InstallAware — and all of them fall short in terms of either quality or functionality. InstallAware is probably the only one that comes close to InstallShield, but the abundance of annoying bugs (from IDE crashes to runtime issues — for example, I was unpleasantly surprised to discover it can’t copy files larger than 2 GB) made me stop using it.
InnoSetup has a wide range of plugins, but in one of my recent projects, I needed to create archives during installation. While there’s already a module for extracting using 7zip (unfortunately, I couldn’t find a working link to the author’s site), I couldn’t find any tools for creating archives. I don’t know if this will be useful to anyone else, but nonetheless — meet the InnoSetup Archive Manager.
And yes, I almost forgot — huge thanks to Henri Gourvest for implementing the 7z.dll API.
Since Inno Setup (more specifically, its Pascal Script engine) has quite a few limitations, I had to get creative in some places. But overall, it turned out quite well. Due to the lack of pointer support (yes, I know about using uint32
, but that approach makes me uneasy), all objects are stored in the memory space of the library itself, so it’s important to call the provided functions in the recommended order.
Downloading#
Or on BitBucket
Usage#
API#
SZNewArchive#
1procedure SZNewArchive(const archTypeName: PAnsiChar; const libDir: PAnsiChar);
2external 'SZNewArchive@files:ArchMan.dll stdcall';
We need to call this to prepare everything in memory:
archTypeName
— archive type (7z
,zip
,rar
)libDir
— directory to look for 7zip library (default:PATH
).
SZAddFile#
1procedure SZAddFile(const fileName: PAnsiChar; const filePath: PAnsiChar);
2external 'SZAddFile@files:ArchMan.dll stdcall';
Add a file to the archive:
fileName
— source file path (e.g.:C:\somefile.dat
);filePath
— file name (with path) in the archive (e.g.:somefolder\anotherfolder\somefile.dat
).
SZAddFiles#
1procedure SZAddFiles(const dir: PAnsiChar; const path: PAnsiChar; const wildCard: PAnsiChar; isRecurse: Boolean);
2external 'SZAddFiles@files:ArchMan.dll stdcall';
The same, but for multiple files:
dir
— source (e.g.:C:\somedir
);path
— target (e.g.:somefolder/anotherfolder
);wildCard
— mask (e.g.:*
);isRecurse
— should it be done recursively or not
SZSetCompressionLevel#
1procedure SZSetCompressionLevel(level: Cardinal);
2external 'SZSetCompressionLevel@files:ArchMan.dll stdcall';
Set compression level (9 - max)
SZSetCompressionMethod#
1procedure SZSetCompressionMethod(const method: PAnsiChar);
2external 'SZSetCompressionMethod@files:ArchMan.dll stdcall';
Method for the archive compression:
- for
zip
:COPY
,DEFLATE
,DEFLATE64
,BZIP2
; - for
7z
:COPY
,LZMA
,LZMA2
,BZIP2
,PPMD
,DEFLATE
,DEFLATE64
.
SZSetProgressHandles#
1procedure SZSetProgressHandles(inWindowHandle: THandle; inProgressBarHandle: THandle);
2external 'SZSetProgressHandles@files:ArchMan.dll stdcall';
Window and progress bar handles to show the progress:
inWindowHandle
— form handle;inProgressBarHandle
— progress bar handle.
SZSaveToFile#
1function SZSaveToFile(const fileName: PAnsiChar): THandle;
2external 'SZSaveToFile@files:ArchMan.dll stdcall';
Start archiving:
fileName
— output, archive name and path
SZIsThreadRunning#
1function SZIsThreadRunning(handle: THandle; timeToWait: Cardinal): Boolean;
2external 'SZIsThreadRunning@files:ArchMan.dll stdcall';
Method for waiting for the process
Example#
1function PackDirectory(dirName: string; fileName: string);
2var
3 ThreadHandle: THandle;
4begin
5 if (not FileExists(ExpandConstant('{tmp}') + '7z.dll'))
6 then ExtractTemporaryFile('7z.dll');
7
8 ForceDirectories(ExtractFileDir(fileName));
9
10 SZNewArchive('zip', ExpandConstant('{tmp}'));
11 SZAddFiles(PAnsiChar(dirName), '', '*', true);
12 SZSetProgressHandles(WizardForm.Handle, RepackProgressBar.Handle);
13
14 ThreadHandle := SZSaveToFile(PAnsiChar(fileName));
15 while (SZIsThreadRunning(ThreadHandle, 200)) do
16 Application.ProcessMessages();
17 CloseHandle(ThreadHandle);
18 end;
19...
20
21PackDirectory(ExpandConstant('{tmp}tmpFilesDir'), ExpandConstant('{app}archive.zip'));