FIX: Pack/delete progress

FIX: Exception at second pack/delete operation
This commit is contained in:
Alexander Koblov 2015-04-19 12:33:46 +00:00
commit 4c502ec3f1
4 changed files with 158 additions and 68 deletions

View file

@ -287,7 +287,7 @@ var
begin
// Try to find archive type in cache
if UpdateFormatsCache.ArchiveName = AFileName then
Exit(TJclUpdateArchiveClassArray(DecompressFormatsCache.ArchiveClassArray))
Exit(TJclUpdateArchiveClassArray(UpdateFormatsCache.ArchiveClassArray))
else begin
UpdateFormatsCache.ArchiveName:= AFileName;
SetLength(UpdateFormatsCache.ArchiveClassArray, 0);
@ -307,7 +307,7 @@ var
begin
// Try to find archive type in cache
if CompressFormatsCache.ArchiveName = AFileName then
Exit(TJclCompressArchiveClassArray(DecompressFormatsCache.ArchiveClassArray))
Exit(TJclCompressArchiveClassArray(CompressFormatsCache.ArchiveClassArray))
else begin
CompressFormatsCache.ArchiveName:= AFileName;
SetLength(CompressFormatsCache.ArchiveClassArray, 0);

View file

@ -49,7 +49,7 @@ implementation
uses
JwaWinBase, Windows, SysUtils, Classes, JclCompression, SevenZip, SevenZipAdv,
SevenZipDlg, SevenZipLng, SevenZipOpt, LazFileUtils;
SevenZipDlg, SevenZipLng, SevenZipOpt, LazFileUtils, SyncObjs;
type
@ -61,7 +61,17 @@ type
{ TSevenZipUpdate }
TSevenZipUpdate = class
TSevenZipUpdate = class(TThread)
FPercent: Int64;
FProgress: TSimpleEvent;
FArchive: TJclCompressionArchive;
public
constructor Create; overload;
constructor Create(Archive: TJclCompressionArchive); overload;
destructor Destroy; override;
public
procedure Execute; override;
function Update: Integer; virtual;
procedure JclCompressionPassword(Sender: TObject; var Password: WideString);
procedure JclCompressionProgress(Sender: TObject; const Value, MaxValue: Int64); virtual;
end;
@ -77,9 +87,11 @@ type
ArchiveName: UTF8String;
ProcessArray: TCardinalArray;
FileName: array of UTF8String;
Archive: TJclDecompressArchive;
ProcessDataProc: TProcessDataProcW;
public
procedure Execute; override;
function Update: Integer; override;
procedure SetArchive(AValue: TJclDecompressArchive);
procedure JclCompressionProgress(Sender: TObject; const Value, MaxValue: Int64); override;
function JclCompressionExtract(Sender: TObject; AIndex: Integer;
var AFileName: TFileName; var Stream: TStream; var AOwnsStream: Boolean): Boolean;
@ -115,11 +127,12 @@ end;
function OpenArchiveW(var ArchiveData : tOpenArchiveDataW) : TArcHandle; stdcall;
var
I: Integer;
Handle: TSevenZipHandle;
ResultHandle: TSevenZipHandle;
Archive: TJclDecompressArchive;
AFormats: TJclDecompressArchiveClassArray;
begin
Handle:= TSevenZipHandle.Create;
with Handle do
ResultHandle:= TSevenZipHandle.Create;
with ResultHandle do
begin
Index:= 0;
ProcessIndex:= 0;
@ -130,10 +143,8 @@ begin
begin
Archive := AFormats[I].Create(ArchiveName, 0, False);
try
Archive.OnPassword:= JclCompressionPassword;
Archive.OnProgress := JclCompressionProgress;
SetArchive(Archive);
Archive.OnExtract:= JclCompressionExtract;
Archive.ListFiles;
Count:= Archive.ItemCount;
@ -146,7 +157,7 @@ begin
ArchiveData.OpenResult:= E_SUCCESS;
Exit(TArcHandle(Handle));
Exit(TArcHandle(ResultHandle));
except
on E: Exception do
begin
@ -169,7 +180,7 @@ begin
with Handle do
begin
if Index >= Count then Exit(E_END_ARCHIVE);
Item:= Archive.Items[Index];
Item:= FArchive.Items[Index];
HeaderData.FileName:= Item.PackedName;
HeaderData.UnpSize:= Int64Rec(Item.FileSize).Lo;
HeaderData.UnpSizeHigh:= Int64Rec(Item.FileSize).Hi;
@ -226,16 +237,14 @@ var
begin
Result:= E_SUCCESS;
if (hArcData <> wcxInvalidHandle) then
with Handle do begin
with Handle do
begin
if OpenMode = PK_OM_EXTRACT then
try
SetLength(ProcessArray, ProcessIndex);
TJclSevenzipDecompressArchive(Archive).ProcessSelected(ProcessArray, OperationMode = PK_TEST);
except
on E: Exception do
Result:= GetArchiveError(E);
begin
Start;
Result:= Update;
end;
Archive.Free;
FArchive.Free;
Free;
end;
end;
@ -282,9 +291,7 @@ begin
begin
Archive := AFormats[I].Create(FileNameUTF8, 0, False);
try
AProgress:= TSevenZipUpdate.Create;
Archive.OnPassword:= AProgress.JclCompressionPassword;
Archive.OnProgress:= AProgress.JclCompressionProgress;
AProgress:= TSevenZipUpdate.Create(Archive);
if (Flags and PK_PACK_ENCRYPT) <> 0 then
begin
@ -328,13 +335,9 @@ begin
Break;
Inc(AddList, Length(FileName) + 1);
end;
try
Archive.Compress;
except
on E: Exception do
Exit(GetArchiveError(E));
end;
Exit(E_SUCCESS);
AProgress.Start;
Exit(AProgress.Update);
finally
Archive.Free;
AProgress.Free;
@ -360,9 +363,7 @@ begin
begin
Archive := AFormats[I].Create(FileNameUTF8, 0, False);
try
AProgress:= TSevenZipUpdate.Create;
Archive.OnPassword:= AProgress.JclCompressionPassword;
Archive.OnProgress:= AProgress.JclCompressionProgress;
AProgress:= TSevenZipUpdate.Create(Archive);
try
Archive.ListFiles;
@ -386,13 +387,9 @@ begin
if FileList^ = #0 then
Break; // end of list
end;
try
Archive.Compress;
except
on E: Exception do
Exit(GetArchiveError(E));
end;
Exit(E_SUCCESS);
AProgress.Start;
Exit(AProgress.Update);
finally
Archive.Free;
AProgress.Free;
@ -446,6 +443,55 @@ end;
{ TSevenZipUpdate }
constructor TSevenZipUpdate.Create;
begin
inherited Create(True);
FProgress:= TSimpleEvent.Create;
end;
constructor TSevenZipUpdate.Create(Archive: TJclCompressionArchive);
begin
inherited Create(True);
FArchive:= Archive;
Archive.Tag:= Self;
FProgress:= TSimpleEvent.Create;
Archive.OnPassword:= JclCompressionPassword;
Archive.OnProgress:= JclCompressionProgress;
end;
destructor TSevenZipUpdate.Destroy;
begin
FProgress.Free;
inherited Destroy;
end;
procedure TSevenZipUpdate.Execute;
begin
try
(FArchive as TJclCompressArchive).Compress;
ReturnValue:= E_SUCCESS;
except
on E: Exception do
ReturnValue:= GetArchiveError(E);
end;
Terminate;
FProgress.SetEvent;
end;
function TSevenZipUpdate.Update: Integer;
var
AllowCancel: Boolean;
begin
AllowCancel:= not (FArchive is TJclUpdateArchive);
while not Terminated do
begin
FProgress.WaitFor(INFINITE);
// If the user has clicked on Cancel, the function returns zero
FArchive.CancelCurrentOperation:= (ProcessDataProcT(PWideChar(FArchive.Items[FArchive.CurrentItemIndex].PackedName), -FPercent) = 0) and AllowCancel;
end;
Result:= ReturnValue;
end;
procedure TSevenZipUpdate.JclCompressionPassword(Sender: TObject;
var Password: WideString);
var
@ -455,33 +501,65 @@ begin
raise ESevenZipAbort.Create(EmptyStr);
end;
procedure TSevenZipUpdate.JclCompressionProgress(Sender: TObject; const Value,
MaxValue: Int64);
procedure TSevenZipUpdate.JclCompressionProgress(Sender: TObject; const Value, MaxValue: Int64);
var
Percent: Int64;
Progress: TSevenZipUpdate;
Archive: TJclUpdateArchive absolute Sender;
begin
if Assigned(ProcessDataProcT) then
begin
Percent:= 1000 + (Value * 100) div MaxValue;
// If the user has clicked on Cancel, the function returns zero
Archive.CancelCurrentOperation:= ProcessDataProcT(PWideChar(Archive.Items[Archive.CurrentItemIndex].PackedName), -Percent) = 0;
end;
Progress:= TSevenZipUpdate(Archive.Tag);
Progress.FPercent:= 1000 + (Value * 100) div MaxValue;
Progress.FProgress.SetEvent;
end;
{ TSevenZipHandle }
procedure TSevenZipHandle.JclCompressionProgress(Sender: TObject; const Value,
MaxValue: Int64);
procedure TSevenZipHandle.Execute;
begin
try
SetLength(ProcessArray, ProcessIndex);
TJclSevenzipDecompressArchive(FArchive).ProcessSelected(ProcessArray, OperationMode = PK_TEST);
ReturnValue:= E_SUCCESS;
except
on E: Exception do
ReturnValue:= GetArchiveError(E);
end;
Terminate;
FProgress.SetEvent;
end;
function TSevenZipHandle.Update: Integer;
begin
while not Terminated do
begin
FProgress.WaitFor(INFINITE);
if Assigned(ProcessDataProc) then
begin
// If the user has clicked on Cancel, the function returns zero
FArchive.CancelCurrentOperation:= ProcessDataProc(PWideChar(FArchive.Items[FArchive.CurrentItemIndex].PackedName), -FPercent) = 0;
end;
end;
Result:= ReturnValue;
end;
procedure TSevenZipHandle.SetArchive(AValue: TJclDecompressArchive);
begin
FArchive:= AValue;
FArchive.Tag:= Self;
AValue.OnPassword := JclCompressionPassword;
AValue.OnProgress := JclCompressionProgress;
AValue.OnExtract := JclCompressionExtract;
end;
procedure TSevenZipHandle.JclCompressionProgress(Sender: TObject; const Value, MaxValue: Int64);
var
Percent: Int64;
Progress: TSevenZipHandle;
Archive: TJclDecompressArchive absolute Sender;
begin
if Assigned(ProcessDataProc) then
begin
Percent:= 1000 + (Value * 100) div MaxValue;
// If the user has clicked on Cancel, the function returns zero
Archive.CancelCurrentOperation:= ProcessDataProc(PWideChar(Archive.Items[Archive.CurrentItemIndex].PackedName), -Percent) = 0;
Progress:= TSevenZipHandle(Archive.Tag);
Progress.FPercent:= 1000 + (Value * 100) div MaxValue;
Progress.FProgress.SetEvent;
end;
end;

View file

@ -778,6 +778,7 @@ type
{ TJclCompressionArchive is not ref-counted }
TJclCompressionArchive = class(TInterfacedObject, IInterface)
private
FTag: Pointer;
FOnProgress: TJclCompressionProgressEvent;
FOnRatio: TJclCompressionRatioEvent;
FOnVolume: TJclCompressionVolumeEvent;
@ -873,6 +874,7 @@ type
property SupportsNestedArchive: Boolean read GetSupportsNestedArchive;
property CancelCurrentOperation: Boolean read FCancelCurrentOperation write FCancelCurrentOperation;
property Tag: Pointer read FTag write FTag;
end;
TJclCompressionArchiveClass = class of TJclCompressionArchive;

View file

@ -1,9 +1,9 @@
jcl/source/common/JclCompression.pas | 45 ++++++++++++++++++++++++++++++------
jcl/source/windows/sevenzip.pas | 8 +++----
2 files changed, 42 insertions(+), 11 deletions(-)
jcl/source/common/JclCompression.pas | 47 ++++++++++++++++++++++++++++++------
jcl/source/windows/sevenzip.pas | 8 +++---
2 files changed, 44 insertions(+), 11 deletions(-)
diff --git a/jcl/source/common/JclCompression.pas b/jcl/source/common/JclCompression.pas
index e5e6a2f..9fcf6f8 100644
index e5e6a2f..6cde31b 100644
--- a/jcl/source/common/JclCompression.pas
+++ b/jcl/source/common/JclCompression.pas
@@ -44,8 +44,7 @@
@ -68,7 +68,12 @@ index e5e6a2f..9fcf6f8 100644
TJclCompressionItemProperty = (ipPackedName, ipPackedSize, ipPackedExtension,
ipFileSize, ipFileName, ipAttributes, ipCreationTime, ipLastAccessTime,
@@ -770,6 +782,7 @@ type
@@ -766,10 +778,12 @@ type
{ TJclCompressionArchive is not ref-counted }
TJclCompressionArchive = class(TInterfacedObject, IInterface)
private
+ FTag: Pointer;
FOnProgress: TJclCompressionProgressEvent;
FOnRatio: TJclCompressionRatioEvent;
FOnVolume: TJclCompressionVolumeEvent;
FOnVolumeMaxSize: TJclCompressionVolumeMaxSizeEvent;
@ -76,7 +81,7 @@ index e5e6a2f..9fcf6f8 100644
FPassword: WideString;
FVolumeIndex: Integer;
FVolumeIndexOffset: Integer;
@@ -855,6 +868,7 @@ type
@@ -855,10 +869,12 @@ type
property OnVolume: TJclCompressionVolumeEvent read FOnVolume write FOnVolume;
property OnVolumeMaxSize: TJclCompressionVolumeMaxSizeEvent read FOnVolumeMaxSize
write FOnVolumeMaxSize;
@ -84,7 +89,12 @@ index e5e6a2f..9fcf6f8 100644
property Password: WideString read FPassword write FPassword;
property SupportsNestedArchive: Boolean read GetSupportsNestedArchive;
@@ -2206,8 +2220,7 @@ const
property CancelCurrentOperation: Boolean read FCancelCurrentOperation write FCancelCurrentOperation;
+ property Tag: Pointer read FTag write FTag;
end;
TJclCompressionArchiveClass = class of TJclCompressionArchive;
@@ -2206,8 +2222,7 @@ const
implementation
uses
@ -94,7 +104,7 @@ index e5e6a2f..9fcf6f8 100644
const
JclDefaultBufferSize = 131072; // 128k
@@ -2218,6 +2231,8 @@ var
@@ -2218,6 +2233,8 @@ var
GlobalStreamFormats: TObject;
GlobalArchiveFormats: TObject;
@ -103,7 +113,7 @@ index e5e6a2f..9fcf6f8 100644
//=== { TJclCompressionStream } ==============================================
constructor TJclCompressionStream.Create(AStream: TStream);
@@ -3743,6 +3758,8 @@ begin
@@ -3743,6 +3760,8 @@ begin
end;
end;
@ -112,7 +122,7 @@ index e5e6a2f..9fcf6f8 100644
{$IFDEF MSWINDOWS}
function OpenFileStream(const FileName: TFileName; StreamAccess: TJclStreamAccess): TStream;
@@ -3887,7 +3904,7 @@ end;
@@ -3887,7 +3906,7 @@ end;
function TJclCompressionItem.GetNestedArchiveName: WideString;
var
ParentArchiveExtension, ArchiveFileName, ArchiveExtension: WideString;
@ -121,7 +131,7 @@ index e5e6a2f..9fcf6f8 100644
begin
if ipPackedName in ValidProperties then
Result := PackedName
@@ -3914,7 +3931,7 @@ begin
@@ -3914,7 +3933,7 @@ begin
else
if ArchiveFileName <> '' then
begin
@ -130,7 +140,7 @@ index e5e6a2f..9fcf6f8 100644
try
ExtensionMap.Delimiter := ';';
ExtensionMap.DelimitedText := Archive.ArchiveSubExtensions;
@@ -7422,7 +7439,14 @@ function TJclSevenzipOpenCallback.CryptoGetTextPassword(
@@ -7422,7 +7441,14 @@ function TJclSevenzipOpenCallback.CryptoGetTextPassword(
password: PBStr): HRESULT;
begin
if Assigned(password) then
@ -145,7 +155,7 @@ index e5e6a2f..9fcf6f8 100644
Result := S_OK;
end;
@@ -7456,7 +7480,14 @@ function TJclSevenzipExtractCallback.CryptoGetTextPassword(
@@ -7456,7 +7482,14 @@ function TJclSevenzipExtractCallback.CryptoGetTextPassword(
password: PBStr): HRESULT;
begin
if Assigned(password) then