Recent

Author Topic: 7zip DLL is super broken  (Read 1994 times)

domasz

  • Hero Member
  • *****
  • Posts: 553
Re: 7zip DLL is super broken
« Reply #15 on: September 11, 2024, 06:36:15 pm »
And now the same but for ZIP:
Code: Pascal  [Select][+][-]
  1.    Arch := CreateOutArchive(CLSID_CFormatZip);
  2.    Arch.SetPropertie('MT', 'off');
  3.    Arch.SetProgressCallback(nil, @ProgressCallback);
  4.  
  5.    // add a file
  6.    Arch.AddFile('...');
  7.    Arch.AddFile('...');
  8.  
  9.   SetCompressionMethod(Arch, mzDeflate);
  10.   SetCompressionLevel(Arch, 1);
  11.  
  12.   // Arch.SetPassword('password');
  13.  
  14.    Str := TFileSTream.Create('....zip', fmCreate);
  15.    Arch.SaveToStream(Str);

Application freezes.

rvk

  • Hero Member
  • *****
  • Posts: 6580
Re: 7zip DLL is super broken
« Reply #16 on: September 11, 2024, 07:18:58 pm »
And now the same but for ZIP:
...
Application freezes.
Works fine for me (without ProgressCallback).
But you don't show what you have in ProgressCallback.


domasz

  • Hero Member
  • *****
  • Posts: 553
Re: 7zip DLL is super broken
« Reply #17 on: September 11, 2024, 09:49:00 pm »
Code: Pascal  [Select][+][-]
  1. function ProgressCallback(sender: Pointer; total: boolean; value: int64): HRESULT; stdcall;
  2. begin
  3.   if total then
  4.     Form1.ProgressBar1.Max := value else
  5.     Form1.ProgressBar1.Position := value;
  6.   Result := S_OK;
  7.  
  8.    Form1.Memo1.Lines.Add(IntToStr(value));
  9. end;

rvk

  • Hero Member
  • *****
  • Posts: 6580
Re: 7zip DLL is super broken
« Reply #18 on: September 11, 2024, 10:00:18 pm »
Code: Pascal  [Select][+][-]
  1. function ProgressCallback(sender: Pointer; total: boolean; value: int64): HRESULT; stdcall;
Also works fine for me.

domasz

  • Hero Member
  • *****
  • Posts: 553
Re: 7zip DLL is super broken
« Reply #19 on: September 12, 2024, 10:10:54 am »
Can you please try the attached in 32 bit Delphi? You might want to replace DLL with another

rvk

  • Hero Member
  • *****
  • Posts: 6580
Re: 7zip DLL is super broken
« Reply #20 on: September 12, 2024, 10:17:16 am »
Can you please try the attached in 32 bit Delphi? You might want to replace DLL with another
Works fine with my 7z.dll (as did the same code in Lazarus).

But why did you include the older 7z.dll in the zip? That's version 9.2. I used 24.8.

rvk

  • Hero Member
  • *****
  • Posts: 6580
Re: 7zip DLL is super broken
« Reply #21 on: September 12, 2024, 10:21:25 am »
Can you please try the attached in 32 bit Delphi? You might want to replace DLL with another
Works fine with my 7z.dll (as did the same code in Lazarus).

But why did you include the older 7z.dll in the zip? That's version 9.2. I used 24.8.
Also just tried with freshly downloaded 7z.dll 9.2 and that works fine too in Delphi.

domasz

  • Hero Member
  • *****
  • Posts: 553
Re: 7zip DLL is super broken
« Reply #22 on: September 12, 2024, 10:23:11 am »
But why did you include the older 7z.dll in the zip? That's version 9.2. I used 24.8.
I tried multiple ones to check the bug and just included the last one I was checking.

Thanks for testing. Now- what Delphi do you have? I have XE

rvk

  • Hero Member
  • *****
  • Posts: 6580
Re: 7zip DLL is super broken
« Reply #23 on: September 12, 2024, 01:33:41 pm »
Thanks for testing. Now- what Delphi do you have? I have XE
I use Delphi 10.2 but in Lazarus it worked fine too.

Arrgh... I now see when this happens.
I didn't have a changed.log in my 7zip directory so it only compressed 1 file.
It ONLY happens if you have multiple files.

I also noticed that with 1 small file, sometimes the TMemo is finished and the TProgressbar lags behind.

I think the freeze might have something to do with threads.

When doing a postmessage to the form it works fine (with multiple files).

Code: Pascal  [Select][+][-]
  1. const
  2.   WM_OK = WM_USER + 1;
  3.  
  4. type
  5.   TForm1 = class(TForm)
  6.     ProgressBar1: TProgressBar;
  7.     Memo1: TMemo;
  8.     Button3: TButton;
  9.     procedure Button3Click(Sender: TObject);
  10.   private
  11.     { Private declarations }
  12.     procedure WMOk(var msg: TMessage); message WM_OK;
  13.   public
  14.     { Public declarations }
  15.   end;
  16.  
  17. var
  18.   Form1: TForm1;
  19.  
  20. implementation
  21.  
  22. {$R *.dfm}
  23.  
  24.  
  25. procedure TForm1.WMOk(var msg: TMessage);
  26. begin
  27.   if boolean(msg.LParam) then
  28.       Form1.ProgressBar1.Max := msg.WParam
  29.   else
  30.       Form1.ProgressBar1.Position := msg.WParam;
  31.   Form1.Memo1.Lines.Add(IntToStr(msg.WParam));
  32. end;
  33.  
  34. function ProgressCallback(Sender: Pointer; total: boolean; value: int64): HRESULT; stdcall;
  35. begin
  36.   Postmessage(Form1.Handle, WM_OK, value, ord(total));
  37.   Result := S_OK;
  38.   {
  39.     if total then
  40.     Form1.ProgressBar1.Max := value else
  41.     Form1.ProgressBar1.Position := value;
  42.     Form1.Memo1.Lines.Add(IntToStr(value));
  43.   }
  44. end;

So the callback is probably run in a different thread and you can't just call Form1 variables like that from different threads.

(With thread you would normally call Synchronise for this, or implement PostMessage like I've done here)
« Last Edit: September 12, 2024, 01:35:30 pm by rvk »

domasz

  • Hero Member
  • *****
  • Posts: 553
Re: 7zip DLL is super broken
« Reply #24 on: September 12, 2024, 01:50:20 pm »
Thank you!

As for threads- that's what this was supposed to take care of:
Code: Pascal  [Select][+][-]
  1. Arch.SetPropertie('MT', 'off');

rvk

  • Hero Member
  • *****
  • Posts: 6580
Re: 7zip DLL is super broken
« Reply #25 on: September 12, 2024, 01:55:47 pm »
Thank you!

As for threads- that's what this was supposed to take care of:
Code: Pascal  [Select][+][-]
  1. Arch.SetPropertie('MT', 'off');
Yes, either that doesn't work... or the 7z.dll is still executed in its own thread.

For example see here https://sourceforge.net/p/sevenzip/discussion/45798/thread/98ec61cf/

There the solution of MT was discussed but we've seen in this topic that passing MT before compression method might reset things. So maybe it's still using multiple threads and cores.

For example... putting the Arch.SetPropertie('MT', 'off'); just before TFileSTream.Create you'll see that it works again.
So... setting that SetCompressionMethod or SetCompressionLevel just resets everything back to the original values (i.e. multiple threads).

domasz

  • Hero Member
  • *****
  • Posts: 553
Re: 7zip DLL is super broken
« Reply #26 on: September 18, 2024, 03:47:13 pm »
Thanks, rvk!

It does the trick but to simplify my code (I have quite some wrappers around sevenzip) I decided to use TStream approach with a custom class.
This thing I can plug anywhere I have a TStream and have a progress bar.


Code: Pascal  [Select][+][-]
  1. TProgCallback = procedure(Total: Boolean; Value: Int64);
  2.  
  3.   TProgressStream = class(TStream)
  4.   private
  5.     FStream: TStream;
  6.     FTotalSize: Int64;
  7.     FTotalWritten: Int64;
  8.   public
  9.     FCallback: TProgCallback;
  10.     constructor Create(Str: TStream; TotalSize: Int64);
  11.     function Write(const Buffer; Count: Longint): Longint; override;
  12.     function Seek(Offset: Longint; Origin: Word): Longint; override;
  13.   end;
  14.  
  15.  
  16. constructor TProgressStream.Create(Str: TStream; TotalSize: Int64);
  17. begin
  18.   inherited Create;
  19.   FStream := Str;
  20.   FTotalSize := TotalSize;
  21.   FTotalWritten := 0;
  22. end;
  23.  
  24. function TProgressStream.Write(const Buffer; Count: Longint): Longint;
  25. begin
  26.   Result := FStream.Write(Buffer, Count);
  27.  
  28.   Inc(FTotalWritten, Count);
  29.  
  30.   FCallback(False, FTotalWritten);
  31. end;
  32.  
  33. function TProgressStream.Seek(Offset: Longint; Origin: Word): Longint;
  34. begin
  35.   Result:= FStream.Seek(Offset, Origin); //doesn't cover all cases
  36. end;
  37.  

 

TinyPortal © 2005-2018