Log in

View Full Version : Progress for 7z unpacking on {app}


danswano
20-08-2017, 10:13
Hello,
How to show progress while inno is unpacking .7z file inside {app} folder like it does to arc?
It's just freezes until it's fully unpacked with no progress then it continue to the other files.
Thanks.

78372
20-08-2017, 21:04
What script are you using?

danswano
20-08-2017, 23:49
The original ISDone:
if not ISExec ( 0, 0, 0, ExpandConstant('{tmp}\7z.exe'), '-o"' + ExpandConstant('{app}') + '" x -y "' + ExpandConstant('{app}\data.001') + '" ', ExpandConstant('{tmp}'), 'extracting, please wait.',false) then break;
DeleteFile(ExpandConstant('{app}\data.001'));

78372
21-08-2017, 04:54
Use IS7ZIPExtract from ISDone

danswano
21-08-2017, 07:58
Cna you paste a modified full line of IS7ZIPExtract to unpack data.001 with passowrd support please?

Gupta
21-08-2017, 08:28
>>Use IS7ZIPExtract from ISDone
can only extract 7z format

here is the answer, understand it yourself

function BufferToAnsi(const Buffer: string): AnsiString;
var
W: Word;
I: Integer;
begin
SetLength(Result, Length(Buffer) * 2);
for I := 1 to Length(Buffer) do
begin
W := Ord(Buffer[I]);
Result[(I * 2)] := Chr(W shr 8); { high byte }
Result[(I * 2) - 1] := Chr(Byte(W)); { low byte }
end;
end;

type
TTimerProc = procedure(H: LongWord; Msg: LongWord; IdEvent: LongWord; Time: LongWord);

function SetTimer(Wnd: LongWord; IDEvent, Elapse: LongWord; TimerFunc: LongWord): LongWord;
external '[email protected] stdcall';
function KillTimer(hWnd: LongWord; uIDEvent: LongWord): BOOL;
external '[email protected] stdcall';

function WrapTimerProc(Callback: TTimerProc; ParamCount: Integer): LongWord;
external 'wrapcallback@files:innocallback.dll stdcall';

var
ProgressPage: TOutputProgressWizardPage;
ProgressFileName: string;

procedure UpdateProgressProc(H: LongWord; Msg: LongWord; Event: LongWord; Time: LongWord);
var
S: AnsiString;
L: Integer;
P: Integer;
Max: Integer;
Progress: string;
Buffer: string;
Stream: TFileStream;
Percent: Integer;
Found: Boolean;
begin
Found := False;
if not FileExists(ProgressFileName) then
begin
Log(Format('Progress file %s does not exist', [ProgressFileName]));
end
else
begin
try
{ Need shared read as the output file is locked for writting, }
{ so we cannot use LoadStringFromFile }
Stream := TFileStream.Create(ProgressFileName, fmOpenRead or fmShareDenyNone);
try
L := Stream.Size;
Max := 100*2014;
if L > Max then
begin
Stream.Position := L - Max;
L := Max;
end;
SetLength(Buffer, (L div 2) + (L mod 2));
Stream.ReadBuffer(Buffer, L);
S := BufferToAnsi(Buffer);
finally
Stream.Free;
end;

if S = '' then
begin
Log(Format('Progress file %s is empty', [ProgressFileName]));
end;
except
Log(Format('Failed to read progress from file %s - %s', [
ProgressFileName, GetExceptionMessage]));
end;
end;

if S <> '' then
begin
{ Log(S); }
P := Pos('Everything is Ok', S);
if P > 0 then
begin
Log('Extraction done');
Percent := 100;
Found := True;
end
else
begin
P := Pos('%', S);
if P > 0 then
begin
repeat
Progress := Copy(S, 1, P - 1);
Delete(S, 1, P);
P := Pos('%', S);
until (P = 0);

P := Length(Progress);
while (P > 0) and
(Progress[P] in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.']) do
begin
Dec(P);
end;

Progress := Copy(Progress, P + 1, Length(Progress) - P);

P := Pos('.', Progress);
if P > 0 then
begin
Progress := Copy(Progress, 1, P - 1);
end;

Percent := StrToInt(Progress);
Log(Format('Percent: %d', [Percent]));
Found := True;
end;
end;
end;

if not Found then
begin
Log('No new data found');
{ no new progress data, at least pump the message queue }
ProgressPage.SetProgress(ProgressPage.ProgressBar. Position, 100);
end
else
begin
ProgressPage.SetProgress(Percent, 100);
ProgressPage.SetText(Format('Extracted: %d%%', [Percent]), '');
end;
end;

procedure ExtractArc(ArcArchivePath: string);
var
ArcExtracterPath: string;
TempPath: string;
CommandLine: string;
Timer: LongWord;
ResultCode: Integer;
S: AnsiString;
Message: string;
begin
ExtractTemporaryFile('7z.exe');
ExtractTemporaryFile('7z.dll');

ProgressPage := CreateOutputProgressPage('Decompression', 'Decompressing archive...');
ProgressPage.SetProgress(0, 100);
ProgressPage.Show;
try
Timer := SetTimer(0, 0, 250, WrapTimerProc(@UpdateProgressProc, 4));

TempPath := ExpandConstant('{tmp}');
ArcExtracterPath := TempPath + '\7z.exe';
ProgressFileName := ExpandConstant('{tmp}\progress.txt');
Log(Format('Expecting progress in %s', [ProgressFileName]));
CommandLine :=
Format('"%s" x -y -o"%s" -bb3 -bsp1 "%s" 1> "%s"', [
ArcExtracterPath, ExpandConstant('{app}'), ArcArchivePath, ProgressFileName]);
Log(Format('Executing: %s', [CommandLine]));
CommandLine := Format('/C "%s"', [CommandLine]);
if not Exec(ExpandConstant('{cmd}'), CommandLine, '', SW_HIDE,
ewWaitUntilTerminated, ResultCode) then
begin
RaiseException('Cannot start extracter');
end
else
if ResultCode <> 0 then
begin
LoadStringFromFile(ProgressFileName, S);
Message := Format('Arc extraction failed failed with code %d', [ResultCode]);
Log(Message);
Log('Output: ' + S);
RaiseException(Message);
end
else
begin
Log('Arc extraction done');
end;
finally
{ Clean up }
Log('Arc extraction cleanup');
KillTimer(0, Timer);
ProgressPage.Hide;
DeleteFile(ProgressFileName);
end;
Log('Arc extraction end');
end;

procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssPostInstall then
begin
ExtractArc(ExpandConstant('{src}\{#ArcArchive}'));
end;
end;

78372
21-08-2017, 09:11
Cna you paste a modified full line of IS7ZIPExtract to unpack data.001 with passowrd support please?

splitted 7zip archives are not supported by ISDone. You can use is7z.dll, but unfortunately it will not work for inno setup 5.3.0 and higher editions.

danswano
21-08-2017, 10:23
>>Use IS7ZIPExtract from ISDone
can only extract 7z format

here is the answer, understand it yourself
[/CODE]

Thanks for the effort, can you strip the arc extraction stage out of the code cause i want to execute the 7z extraction after the arc isarcextract is finished.
I mean i want to extract the arc from {src} then extract the 7z from {app}
7z multi parts are packed inside the arc file.

danswano
28-08-2017, 01:51
danswano
if not ISArcExtract ( 0, 0, ExpandConstant('{src}\arc.arc'), ExpandConstant('{app}\'), '', false, '', ExpandConstant('{tmp}\arc.ini'), ExpandConstant('{app}\'), notPCFonFLY{PCFonFLY}) then break;
if not IS7ZipExtract ( 0, 0, ExpandConstant('{app}\CODMW2.7z'), ExpandConstant('{app}\'), false, '') then break;

It won't work with multi part 7z .001 .002 etc ..

vint56
28-08-2017, 03:19
danswano
Then use WinRar there too there is an opportunity to break into archives

ISDone does not support unpacking of 7z multi-volume files only from rar

[Files]
Source: Include\7z.exe; DestDir: {tmp}; Flags: dontcopy

procedure CurStepChanged(CurStep: TSetupStep);

ExtractTemporaryFile('7z.exe');

if not ISExec ( 0, 0, 0, ExpandConstant('{tmp}\7z.exe'), '-o"' + ExpandConstant('{app}') + '" x -y -pPASSWORD "' + ExpandConstant('{src}\bundles.7z.001') + '" ', ExpandConstant('{tmp}'), '...',false) then break;

danswano
28-08-2017, 03:31
Thanks

danswano
28-08-2017, 05:52
One more question please!
Is it possible to split rar into discs and let inno ask for the next part on the next disc?
like data.rar on disc 1
and data.r0 on disc 2?

vint56
28-08-2017, 07:34
danswano
if not ISArcExtract ( 0, 0, ExpandConstant('{src}\Disk-1.arc'), ExpandConstant('{app}\'), '', false, '', ExpandConstant('{tmp}\arc.ini'), ExpandConstant('{app}\'), notPCFonFLY{PCFonFLY}) then break;
if not ShowChangeDiskWindow ('Пожалуйста, вставьте второй диск и дождитесь его инициализации.', ExpandConstant('{src}'),'Disk-2.arc') then break;
if not ISArcExtract ( 0, 0, ExpandConstant('{src}\Disk-2.arc'), ExpandConstant('{app}\'), '', false, '', ExpandConstant('{tmp}\arc.ini'), ExpandConstant('{app}\'), notPCFonFLY{PCFonFLY}) then break;
if not ISRarExtract ( 0, 0, ExpandConstant('{app}\xxx.part01.rar'), ExpandConstant('{app}'), false, '') then break;

danswano
28-08-2017, 09:58
Thanks but i meant directly without packing into arc files.

vint56
28-08-2017, 22:32
danswano
if not ISRarExtract ( 0, 0, ExpandConstant('{src}\xxx.part01.rar'), ExpandConstant('{app}'), false, '') then break;
if not ShowChangeDiskWindow ('Пожалуйста, вставьте второй диск и дождитесь его инициализации.', ExpandConstant('{src}'),'xxx.part02.rar') then break;
if not ISRarExtract ( 0, 0, ExpandConstant('{src}\xxx.part02.rar'), ExpandConstant('{app}'), false, '') then break;

danswano
29-08-2017, 00:32
I did that before i ask you and i got a clear message that it's not supported, did you test that?

vint56
29-08-2017, 00:43
danswano
I'm sorry my mistake
multipart .rar archives with the data on different disks are not supported!