AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Schwierigkeiten mit 7-zip und Events
Thema durchsuchen
Ansicht
Themen-Optionen

Schwierigkeiten mit 7-zip und Events

Ein Thema von a.def · begonnen am 5. Dez 2016 · letzter Beitrag vom 6. Dez 2016
Antwort Antwort
mensch72

Registriert seit: 6. Feb 2008
838 Beiträge
 
#1

AW: Schwierigkeiten mit 7-zip und Events

  Alt 5. Dez 2016, 16:20
http://docwiki.embarcadero.com/RADSt...andling_Method

es fehlt dir wohl noch der "MessageMap" im Form
Delphi-Quellcode:
protected
   procedure UserMsgProc(var Message: TMessage); message WM_USER;
end;
(und ich würde statt "Application.ProcessMessages;" lieber "ProgressBar1 .Update .Repaint .Invalidate" verwenden wenn es das gibt. Wenn etwas nur mit "ProcessMessages" geht, ist meist das Konzept nicht so wirklich gut)

Geändert von mensch72 ( 5. Dez 2016 um 16:24 Uhr)
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.277 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: Schwierigkeiten mit 7-zip und Events

  Alt 5. Dez 2016, 16:24
Hallo,
wenn intern ein Thread benutzt wird, fehlt vielleicht nur Synchronize beim Upate der GUI im Hauptprogramm.
Heiko
  Mit Zitat antworten Zitat
a.def
(Gast)

n/a Beiträge
 
#3

AW: Schwierigkeiten mit 7-zip und Events

  Alt 5. Dez 2016, 17:23
http://docwiki.embarcadero.com/RADSt...andling_Method

es fehlt dir wohl noch der "MessageMap" im Form
Delphi-Quellcode:
protected
   procedure UserMsgProc(var Message: TMessage); message WM_USER;
end;
(und ich würde statt "Application.ProcessMessages;" lieber "ProgressBar1 .Update .Repaint .Invalidate" verwenden wenn es das gibt. Wenn etwas nur mit "ProcessMessages" geht, ist meist das Konzept nicht so wirklich gut)
In der offiziellen JEDI-Demo ist er auch nicht vorhanden und dort funktioniert das Aktualisieren der GUI auch nicht.

Hallo,
wenn intern ein Thread benutzt wird, fehlt vielleicht nur Synchronize beim Upate der GUI im Hauptprogramm.
Mein Code wird im Hauptthread ausgeführt.

Ich habe mal ein bisschen rumgespielt und den Code im Button in Folgendes gepackt
Delphi-Quellcode:
TThread.CreateAnonymousThread(
 procedure
  begin
  end).Start:
Dann funktioniert es. Aber warum nicht schon mit PostMessage usw.? Damit habe ich es ja auch versucht.

Geändert von a.def ( 5. Dez 2016 um 17:28 Uhr)
  Mit Zitat antworten Zitat
Ghostwalker

Registriert seit: 16. Jun 2003
Ort: Schönwald
1.299 Beiträge
 
Delphi 10.3 Rio
 
#4

AW: Schwierigkeiten mit 7-zip und Events

  Alt 5. Dez 2016, 17:34
Jaja.....nur die DLL, die nutzt sehr wohl Threads.
Uwe
e=mc² or energy = milk * coffee²
  Mit Zitat antworten Zitat
mensch72

Registriert seit: 6. Feb 2008
838 Beiträge
 
#5

AW: Schwierigkeiten mit 7-zip und Events

  Alt 5. Dez 2016, 18:13
wenn du magst, hänge das gezippte Projekt deines "MiniTestProg" mal hier an eine Antwort an. Wenn ich am WE dazu komme kann ich mal schaun was mein PC dazu sagt

Bei deinem "TThread.CreateAnonymousThread" ist es mir nicht ganz wohl, du entkoppelst dich zwar von dem externen DLL Thread, aber echt sauber im MainThread der VCL bist du so auch noch nicht.

Das PostMessage mit einer "selbst gemappten" MessageProc oder einer Komponente ala "AppMessage" wo man sich seine Message im Event raussucht wäre mir hier für alles was ich sonst noch in der GUI vor hätte die sicherste und einfachste Lösung. Man kann das sicher auch mit eigenen (Async)Threads oder Synchronize hinbekommen, aber als fauler Mensch fehlt mir dazu der Elan.
  Mit Zitat antworten Zitat
a.def
(Gast)

n/a Beiträge
 
#6

AW: Schwierigkeiten mit 7-zip und Events

  Alt 5. Dez 2016, 18:57
Ich poste hier mal meine erste halbwegs funktionierende Lösung.
Aktuell funktioniert ZIP und 7z. GZip warum auch immer noch nicht.

Delphi-Quellcode:
const
 WM_SYNC_ARCHIVE_PROGRESS = WM_USER + 153;

procedure TForm1.WMSyncArchiveProgress(var Message: TMessage);
begin
 ProgressBar1.Max := Message.LParam;
 ProgressBar1.Position := Message.WParam;
end;

procedure TForm1.JclCompressionArchiveProgress(Sender: TObject; const Value, MaxValue: Int64);
var
 MyValue, MyMaxValue: Int64;
begin
 MyValue := Value;
 MyMaxValue := MaxValue;

 while MyMaxValue > High(Byte) do
  begin
   MyMaxValue := MyMaxValue shr 8;
   MyValue := MyValue shr 8;
  end;

 PostMessage(Handle, WM_SYNC_ARCHIVE_PROGRESS, MyValue, MyMaxValue);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
 aFile: string;
 aCompressArchive: TJclCompressionArchive;
 aCompressFormat: TJclCompressArchiveClass;
begin
 TThread.CreateAnonymousThread(
   procedure
  begin
   aFile := ExtractFilePath(Application.ExeName) + Edit1.Text; // Edit1 z.B. "Test.7z" oder "Test.zip"
   aCompressFormat := GetArchiveFormats.FindUpdateFormat(aFile);

   if aCompressFormat <> nil then
    begin
     Caption := 'Compressing ...';

     aCompressArchive := aCompressFormat.Create(aFile);

     try
      aCompressArchive.OnProgress := JclCompressionArchiveProgress;
      aCompressArchive.Password := '123456';

      (aCompressArchive as TJclCompressArchive).AddFile('249MB.123', 'E:\7ztest\249MB.123');
      (aCompressArchive as TJclCompressArchive).AddFile('456.txt', 'E:\7ztest\123\456.txt');
      (aCompressArchive as TJclCompressArchive).AddFile('456', 'E:\7ztest\456');

      if (aCompressArchive.ClassType = JCLCompression.TJcl7zCompressArchive) or (aCompressArchive.ClassType = JCLCompression.TJcl7zUpdateArchive) then
       begin
        ShowMessage('7z');

        // - SetEncryptionMethod for 7z not available
        (aCompressArchive as TJcl7zUpdateArchive).SetCompressionLevel(6); // 0 .. 9
        (aCompressArchive as TJcl7zUpdateArchive).SetCompressHeader(True);

        if aCompressArchive.Password <> 'then
         (aCompressArchive as TJcl7zUpdateArchive).SetEncryptHeader(True);
       end
      else if (aCompressArchive.ClassType = JCLCompression.TJclZIPCompressArchive) or (aCompressArchive.ClassType = JCLCompression.TJclZipUpdateArchive) then
       begin
        ShowMessage('zip');

        // - SetEncryptHeader/SetCompressHeader for zip not available
        (aCompressArchive as TJclZipUpdateArchive).SetNumberOfPasses(3);
        (aCompressArchive as TJclZipUpdateArchive).SetCompressionLevel(7); // 0 .. 9
        (aCompressArchive as TJclZipUpdateArchive).SetCompressionMethod(TJclCompressionMethod.cmDeflate);

        if aCompressArchive.Password <> 'then
         (aCompressArchive as TJclZipUpdateArchive).SetEncryptionMethod(emAES256); // emNone, emAES128, emAES192, emAES256, emZipCrypto
       end
      else if (aCompressArchive.ClassType = JCLCompression.TJclGZipCompressArchive) or (aCompressArchive.ClassType = JCLCompression.TJclGZipUpdateArchive) then
       begin
        ShowMessage('Gzip');

        (aCompressArchive as TJclGZipUpdateArchive).SetCompressionLevel(7); // 0 .. 9
        (aCompressArchive as TJclGZipUpdateArchive).SetNumberOfPasses(3);
       end
      else
       FreeAndNil(aCompressArchive);

      if aCompressArchive <> nil then
       (aCompressArchive as TJclCompressArchive).Compress; // Funktioniert bei Gzip noch nicht
     finally
      FreeAndNil(aCompressArchive);

      Caption := 'Done';
     end;
    end;
  end).Start;
end;
Zitat:
Bei deinem "TThread.CreateAnonymousThread" ist es mir nicht ganz wohl, du entkoppelst dich zwar von dem externen DLL Thread, aber echt sauber im MainThread der VCL bist du so auch noch nicht.
Das ist nur zu Testzwecken. Aber letztlich läuft es eh darauf hinaus, dass das alles in einem TThread landet.

Geändert von a.def ( 5. Dez 2016 um 19:03 Uhr)
  Mit Zitat antworten Zitat
mensch72

Registriert seit: 6. Feb 2008
838 Beiträge
 
#7

AW: Schwierigkeiten mit 7-zip und Events

  Alt 6. Dez 2016, 09:25
"Caption := " und "ShowMessage" wieder/noch einfach so in einem (Anonymous)Thread... auch wenn nur zum schnellen Test... das geht so nicht auf Dauer gut
  Mit Zitat antworten Zitat
a.def
(Gast)

n/a Beiträge
 
#8

AW: Schwierigkeiten mit 7-zip und Events

  Alt 6. Dez 2016, 09:45
Mein viel größeres Problem besteht darin festzustellen, wann eine Datei fertig komprimiert wurde. Dafür bietet JCL leider kein Event.
Meine behilfsmäßige Lösung ist sehr kompliziert und funktioniert nur bei größeren Dateien und das ist ja nicht Sinn der Sache
Sinn dahinter ist, dass ich zählen möchte wie viele Dateien vollständig komprimiert wurden + deren Dateigrößen möchte ich auch festhalten.
Mit einem vernünftigen Event wie "OnProgressFileFinished" oder so wär das alles kein Problem.

Delphi-Quellcode:
var
 iFileSizeOld, iFileSizeCompressed: Int64;
 iFilesCompressed, iCurrentItem: Integer;

procedure TForm1.JclCompressionArchiveProgress(Sender: TObject; const Value, MaxValue: Int64);
 function getPercent(const aBase, aValue: Extended): ShortInt;
 begin
  if (aValue > 0) and (aBase > 0) then
   Result := Trunc((aValue / aBase * 100) + 0.5)
  else
   Result := 0;
 end;

var
 iTmpPos, iTmp: Integer;
begin
 iTmpPos := getPercent(MaxValue, Value);
 if (iTmpPos <> ProgressBar1.Position) or (iTmpPos = ProgressBar1.Max) then
  begin
   if ((Sender as TJclCompressionArchive).ItemCount > iFilesCompressed) then
    begin
     ProgressBar1.Position := iTmpPos;
     iFileSizeOld := (Sender as TJclCompressionArchive).Items[iFilesCompressed].FileSize;
     iTmp := getPercent(iFileSizeOld, Value - iFileSizeCompressed);

     if iTmp >= 100 then // bei größeren Dateien kann man hier davon ausgehen, dass sie fertig komprimiert wurde
      begin
       inc(iFileSizeCompressed, iFileSizeOld);

       if iFilesCompressed < (Sender as TJclCompressionArchive).ItemCount then
        begin
         ShowMessage('Datei fertig');
         inc(iFilesCompressed);
        end;
      end;
    end;
  end;
end;
Edit
ich habe das Ganze jetzt mal etwas gekürzt und nun funktioniert es auch mit sehr kleinen Dateien (< 10 Byte etc).
Delphi-Quellcode:
var
 iFileCount, iFileSizeOld, iFileSizeCompressed: Int64;
 iFilesCompressed: Integer;

// ... Button der das Archiv erzeugt...
// ...
 iFileCount := 2; // Nur Dateien werden hier gezählt. Leere Verzeichnisse werden von JCL anders erstellt
 (aCompressArchive as TJclCompressArchive).AddFile('kleinedatei 1.txt', 'E:\7ztest\kleinedatei 1.txt');
 (aCompressArchive as TJclCompressArchive).AddFile('kleinedatei 2.txt', 'E:\7ztest\kleinedatei 2.txt');
// ...

procedure TForm1.JclCompressionArchiveProgress(Sender: TObject; const Value, MaxValue: Int64);
 function getPercent(const aBase, aValue: Extended): ShortInt;
 begin
  if (aValue > 0) and (aBase > 0) then
   Result := Trunc((aValue / aBase * 100) + 0.5)
  else
   Result := 0;
 end;

begin
 if (iFilesCompressed < iFileCount) then
  begin
   ProgressBar1.Position := getPercent(MaxValue, Value);
   iFileSizeOld := (Sender as TJclCompressionArchive).Items[iFilesCompressed].FileSize;
   if (Value >= (iFileSizeOld + iFileSizeCompressed)) then
    begin
     inc(iFilesCompressed);
     inc(iFileSizeCompressed, iFileSizeOld);
    end;
  end;
end;

Geändert von a.def ( 6. Dez 2016 um 18:07 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:59 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz