我正在使用这段代码:How to add .arc decompression to Inno Setup?(Martin Prikryl 的回答)。我想在解压缩页面添加一个取消按钮,并激活此页面的其他功能(当解压缩处于活动状态时,此页面处于非活动状态,例如,我无法按下音乐实现的开/关按钮)。
如何在解压页面添加取消按钮?以及如何激活此页面的其他功能?
我已经使用 unarc.dll
(来自 FreeArc+InnoSetup 包
ISFreeArcExtract v.4.0.rar
)重新实现了 How to add .arc decompression to Inno Setup?的解决方案。
大大简化了代码,也更容易添加取消解压的功能。
#define ArcArchive "test.arc"
[Files]
Source: unarc.dll; Flags: dontcopy
[Code]
const
ArcCancelCode = -10;
function FreeArcExtract(
Callback: LongWord;
Cmd1, Cmd2, Cmd3, Cmd4, Cmd5, Cmd6, Cmd7, Cmd8, Cmd9, Cmd10: PAnsiChar
): Integer;
external 'FreeArcExtract@files:unarc.dll cdecl';
const
CP_UTF8 = 65001;
function WideCharToMultiByte(CodePage: UINT; dwFlags: DWORD;
lpWideCharStr: string; cchWideChar: Integer; lpMultiByteStr: AnsiString;
cchMultiByte: Integer; lpDefaultCharFake: Integer;
lpUsedDefaultCharFake: Integer): Integer;
external '[email protected] stdcall';
function GetStringAsUtf8(S: string): AnsiString;
var
Len: Integer;
begin
Len := WideCharToMultiByte(CP_UTF8, 0, S, Length(S), Result, 0, 0, 0);
SetLength(Result, Len);
WideCharToMultiByte(CP_UTF8, 0, S, Length(S), Result, Len, 0, 0);
end;
var
ArcTotalSize: Integer;
ArcExtracted: Integer;
ArcCancel: Boolean;
ArcProgressPage: TOutputProgressWizardPage;
function FreeArcCallback(
AWhat: PAnsiChar; Int1, Int2: Integer; Str: PAnsiChar): Integer;
var
What: string;
begin
What := AWhat;
if What = 'origsize' then
begin
ArcTotalSize := Int1;
Log(Format('Total size of files to be extracted is %d MB', [ArcTotalSize]));
end
else
if What = 'write' then
begin
if ArcTotalSize > 0 then
begin
ArcProgressPage.SetProgress(Int1, ArcTotalSize);
end;
ArcExtracted := Int1;
end
else
begin
// Just to pump message queue more often (particularly for 'read' callbacks),
// to get more smooth progress bar
if (ArcExtracted > 0) and (ArcTotalSize > 0) then
begin
ArcProgressPage.SetProgress(ArcExtracted, ArcTotalSize);
end;
end;
if ArcCancel then Result := ArcCancelCode
else Result := 0;
end;
function FreeArcCmd(
Cmd1, Cmd2, Cmd3, Cmd4, Cmd5, Cmd6, Cmd7, Cmd8, Cmd9, Cmd10: string): Integer;
begin
ArcCancel := False;
try
Result :=
FreeArcExtract(
CreateCallback(@FreeArcCallback),
GetStringAsUtf8(Cmd1), GetStringAsUtf8(Cmd2), GetStringAsUtf8(Cmd3),
GetStringAsUtf8(Cmd4), GetStringAsUtf8(Cmd5), GetStringAsUtf8(Cmd6),
GetStringAsUtf8(Cmd7), GetStringAsUtf8(Cmd8), GetStringAsUtf8(Cmd9),
GetStringAsUtf8(Cmd10));
Log(Format('Arc command "%s" result %d', [Cmd1, Result]));
except
Result := -63;
end;
end;
function UnPackArchive(ArchivePath: string; DestPath: string): Integer;
begin
{ Find out length of files to be extracted - origsize }
Result := FreeArcCmd('l', '--', ArchivePath, '', '', '', '', '', '', '');
if Result = 0 then
begin
// Actually extract
Result :=
FreeArcCmd('x', '-o+', '-dp' + DestPath, '-w' + DestPath, '--', ArchivePath,
'', '', '', '');
end;
end;
procedure UnpackCancelButtonClick(Sender: TObject);
begin
ArcCancel := True;
end;
procedure ExtractArc;
var
ArcArchivePath: string;
UnpackResult: Integer;
PrevCancelButtonClick: TNotifyEvent;
Error: string;
begin
ArcProgressPage :=
CreateOutputProgressPage('Decompression', 'Decompressing archive...');
ArcProgressPage.SetProgress(0, 100);
ArcProgressPage.Show;
try
WizardForm.CancelButton.Visible := True;
WizardForm.CancelButton.Enabled := True;
PrevCancelButtonClick := WizardForm.CancelButton.OnClick;
WizardForm.CancelButton.OnClick := @UnpackCancelButtonClick;
ArcArchivePath := ExpandConstant('{src}\{#ArcArchive}');
Log(Format('Arc extraction starting - %s', [ArcArchivePath]));
ArcExtracted := 0;
UnpackResult := UnPackArchive(ArcArchivePath, ExpandConstant('{app}'));
if UnpackResult <> 0 then
begin
if ArcCancel then
begin
Error := 'Extraction cancelled';
end
else
begin
Error := Format('Extraction failed with code %d', [UnpackResult]);
end;
MsgBox(Error, mbError, MB_OK);
end;
finally
Log('Arc extraction cleanup');
ArcProgressPage.Hide;
WizardForm.CancelButton.OnClick := PrevCancelButtonClick;
end;
end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssPostInstall then
begin
ExtractArc;
end;
end;
CreateCallback
函数,您需要 Inno Setup 6。如果您无法使用 Inno Setup 5,您可以使用 InnoTools InnoCallback库中的
WrapCallback
函数。
代码提取一个单独的 .arc 文件。如果您想将存档嵌入到安装程序中,您可以使用
[Files]
Source: {#ArcArchive}; DestDir: "{tmp}"; Flags: nocompression deleteafterinstall
并从
{tmp}
中提取存档:
ArcArchivePath := ExpandConstant('{tmp}\{#ArcArchive}');
请注意,来自
unarc.dll
的 ISFreeArcExtract v.4.0.rar
似乎不支持密码保护的存档。 ISFreeArcExtract v.4.2.rar
的版本可以,但我不知道值得信赖的下载链接。
如果要解压多个压缩包,请参见Inno Setup - 如何添加多个arc文件进行解压?
你需要的就是这个 http://fileforums.com/showthread.php?t=96619
该程序与 inno setup 具有最新兼容性,并且还支持具有多个扩展名的基于密码的文件。