DotNetZip - Extract Progress

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    DotNetZip - Extract Progress

    Moin Moin, ich habe ein Problem.

    Und zwar möchte ich währenddessen ich eine Datei unzippe einen Progress haben, welcher in form einer ProgressBar wiedergegeben wird.

    So sieht der Code aus zum entpacken:

    VB.NET-Quellcode

    1. ​Private Async Function Downloader_DownloadFileCompletedAsync(ByVal sender As Object, ByVal e As System.ComponentModel.AsyncCompletedEventArgs) As Task Handles downloader.DownloadFileCompleted
    2. Await Task.Run(Sub()
    3. Dim ZipToUnpack As String = "Patch.zip"
    4. Using zip1 As ZipFile = ZipFile.Read(ZipToUnpack)
    5. Dim patch As ZipEntry
    6. For Each patch In zip1
    7. patch.Extract(ExtractExistingFileAction.OverwriteSilently)
    8. Next
    9. File.Delete("patch.rar")
    10. End Using
    11. End Sub)
    12. ....
    13. End Function


    Jedoch weiß ich nicht, wie ich den Progress ausgeben soll.

    Verwendet wird DotNetZip

    archive.codeplex.com/?p=dotnetzip

    Würde mich über eure Hilfe freuen.

    Mfg
    @xArva Mach Dir ne ProgressBar, deren Maximum auf die Anzahl der Dateien und nach jeder Datei inkrementierst Du diese.
    docs.microsoft.com/de-de/dotne…t?view=netframework-4.7.2
    Feddich.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    xArva schrieb:


    Ich benutze keinen BackgroundWorker, da sich die Form sonst immer beim entpacken einfriert, leider.


    Ach, wo genau siehst Du in der Solution 4 den Backgroundworker? Den verwende ich auch seit Jahren nicht mehr. Tante Google ist wirklich hilfreich, wenn man sie fragt.
    Was mich an der Solution 4 stört ist "nur" Application.DoEvents().

    Oops, wenn Dir die Form beim Backgroundworker einfriert machst Du eh was falsch.

    Async + IProgress = "Asynchrone Rückmeldung"

    Hi.

    Da Du schon Async benutzt, ist der Trick das IProgress-Interface zu nutzen.

    Ich habe das gerade vor kurzem selbst versucht, und es geht.

    Dazu gehören leider mehr Teile als einem lieb ist, aber wenn die "Zutaten" einmal bereitliegen, kann der Eintopf schmoren... (Hmmm?! Hunger?)

    Wenn der Asynchrone Task aufgerufen wird einem IProgess die "Berichts-Klasse" übergeben.

    Kurz einmal die "Berichts-Klasse" namens UnZipperProgress.

    1. Methode

    VB.NET-Quellcode

    1. Public Class UnZipperProgress
    2. Public Property StatusMessage As String 'Um evtl. Text auszugeben
    3. Public Property Completed As Integer 'evtl. aktueller Prozentsatz
    4. Public Property Maximum As Integer 'für ein Progressbar-Maximum
    5. 'evtl. Methoden um Text/Prozentwert berechnen etc.
    6. End Class


    Das ist die "Variable" die unseren Verlauf/Progress enthält.

    Damit ist noch keine Vegane Bockwurst im Topf.

    Zudem brauchen wir eine zusätzliche Methode, die "Berichts-Ereignisse" behandelt, namens "DoReport".

    VB.NET-Quellcode

    1. Private Sub DoReport(sender As Object, e As UnZipperProgress)
    2. 'Variablen aus dem e übergeben, nur um es zu verdeutlichen!
    3. Dim StatusText = e.StatusMessage
    4. Dim ProgressValue = e.Completed
    5. Dim ProgressMaximum = e.Maximum
    6. 'Hier wird der UI-Task aufgerufen, System bedingt so kompliziert...
    7. 'TbContent ein TextBlock, ProgressBarStatus ein ProgressBar.
    8. Me.Dispatcher.Invoke(Sub()
    9. TbContent.Text = StatusText 'UI Textausgabe
    10. ProgressBarStatus.Maximum = ProgressMaximum 'UI-Maximum im ProgressBar
    11. ProgressBarStatus.Value = ProgressValue 'UI-Wert im ProgressBar
    12. End Sub)
    13. End Sub


    Jetzt in deinem "Downloader_DownloadFileCompletedAsync" wir alles, verschoben in eine neue "Async Function".
    Ersteinmal deine "VollständigDownloaded", danach folgt die neue Funktion.

    VB.NET-Quellcode

    1. Private Async Function Downloader_DownloadFileCompletedAsync(ByVal sender As Object, ByVal e As System.ComponentModel.AsyncCompletedEventArgs) As Task Handles downloader.DownloadFileCompleted
    2. Dim progress As New Progress(Of UnZipperProgress) 'Erstellen des Verlaufsobjekts
    3. AddHandler progress.ProgressChanged, AddressOf DoReport 'Verknüpfen des Verlaufs mit dem "Berichts-Ereigniss" (DoReport)
    4. Await AsyncUnZipperWithProgressReport(progress) 'Aufruf des Unzippers mit dem "progress"
    5. End Function


    Jetzt das Entpacken.


    VB.NET-Quellcode

    1. Private Async Function AsyncUnZipperWithProgressReport(progress As IProgress(Of UnZipperProgress)) As Task
    2. Dim reporter As New UnZipperProgress() 'Ein Objekt um den Verlauf aufzunehmen (Redundant)
    3. reporter.StatusMessage = "Started: " & Now.ToLocalTime() 'Start-Text dem reporter übergeben
    4. 'Bemerkung: reporter ist nur als Behälter für den "progress"-Parameter
    5. 'hier wird der Verlauf aufgerufen...
    6. progress.Report(reporter) 'Erster Aufruf des Verlaufs... -> bla.Report(werMachtRaport) <-
    7. Await Task.Run(Sub()
    8. Dim ZipToUnpack As String = "Patch.zip"
    9. Using zip1 As ZipFile = ZipFile.Read(ZipToUnpack)
    10. reporter.StatusMessage = "Entpacke: " & ZipToUnpack
    11. Dim patch As ZipEntry
    12. 'evtl. hier das Maximum an den Reporter übergeben
    13. 'reporter.Maximum = patch.MaximumWert '<- Weiss nicht wie das geht?
    14. reporter.Value = 0
    15. progress.Report(reporter) 'Wenn geänderte Werte aufruf des Report.
    16. For Each patch In zip1
    17. Path.Extract(ExtractExistingFileAction.OverwriteSilently)
    18. reporter.Value += 1
    19. progress.Report(reporter) 'Aufruf des Report.
    20. Next
    21. File.Delete("patch.rar")
    22. End Using
    23. End Sub)
    24. End Function


    Ich habe noch nicht die Möglichkeit des Entpackens vertieft.
    Wenn der Verlauf/Report auch die einzelnen gepackten Dateien innerhalb des "For Each patch" (path?) als Fortschritt behandeln soll,
    muss der Progress mit einem Handler für die Unzip-API behandelt werden.
    Das wird im link von @Dksksm erklärt.

    Das ist eigentlich was Du brauchst, aber ich hatte nur Eintopf im Kopf... (Wirsing?)

    2. Methode

    VB.NET-Quellcode

    1. 'Zitat des links
    2. Private Sub Zip_ExtractProgress(ByVal sender As Object, ByVal e As ExtractProgressEventArgs)
    3. 'ExtractProgressEventArgs ist der Ereignis-Typ der Unzipper-API


    Also könnte DoReport so abgewandelt werden...

    VB.NET-Quellcode

    1. Private Sub DoReport(sender As Object, e As ExtractProgressEventArgs)
    2. If e.EventType = ZipProgressEventType.Extracting_BeforeExtractEntry then
    3. 'Dim StatusText = e.FileName ???
    4. Dim ProgressValue = Convert.ToInt16((e.BytesTransferred / e.TotalBytesToTransfer) '??? mal einhundert ???
    5. Dim ProgressMaximum = e.TotalBytesToTransfer
    6. End If
    7. End Sub


    Und deine Ursprüngliche "Download_Complete" Funktion nicht wie vorher Erklärt einsetzten sonder nur erweitern.


    VB.NET-Quellcode

    1. Private Async Function Downloader_DownloadFileCompletedAsync(ByVal sender As Object, ByVal e As System.ComponentModel.AsyncCompletedEventArgs) As Task Handles downloader.DownloadFileCompleted
    2. Await Task.Run(Sub()
    3. Dim ZipToUnpack As String = "Patch.zip"
    4. Using zip1 As ZipFile = ZipFile.Read(ZipToUnpack)
    5. Dim patch As ZipEntry
    6. AddHandler zip1.ProgressChanged, AddressOf DoReport 'Verknüpfen des Verlaufs mit dem "Berichts-Ereigniss" (DoReport)
    7. For Each patch In zip1
    8. patch.Extract(ExtractExistingFileAction.OverwriteSilently)
    9. Next
    10. File.Delete("patch.rar")
    11. RemoveHandler zip1.ProgressChanged, AddressOf DoReport 'Verknüpfen des Verlaufs mit dem "Berichts-Ereigniss" auflösen!!!
    12. End Using
    13. End Sub)
    14. End Function[sup][/sup]


    Also ist das ganze mit dem IProgress nicht notwendig, aber ich würde das eher einsetzen.
    Bitte nicht den Quellkode einfach übernehmen, ist einfach ausführlicher ausgeschrieben, aber nicht getestet.

    Sich einmal mit der ersten Methode zu befassen, hat den Vorteil auch UI-Tasks und komplexere "Raporte" zu generieren, mit hilfe des herumreichen eines Objekts. ;)

    Zum Beispiel könnte der "Report" mehrer ProgressBars gleichzeitig updaten, indem Der gesamte Vorgang und die einzelnen Dateien einen Report schicken.
    Somit müsste dann die erste Methode verwendet werden, die "UnZipperProgress" erweitert werden, und ein zweiter "Handler" benutzt werden, der abermals
    den ersten "Handler" aufruft und Werte "Raportiert".

    Was? Kein Eintopf, wieder nur Salat? Männo...

    Ich mach mal Pause...

    c.u. Joshi

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Joshi“ ()

    xArva schrieb:

    Und wie?
    Was?
    Keine Eigenleistung?
    Keine Eigeninitiative?
    Nur C&P-Code?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!