BackUpTool für ein Programm

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

Es gibt 24 Antworten in diesem Thema. Der letzte Beitrag () ist von INOPIAE.

    BackUpTool für ein Programm

    Moin moin

    Ich benötige etwas Hilfe. Ich habe ja diese kleine "WetterApp" für mein Opa programmiert. Nun ist es von Nöten dafür ein BackUp-Tool zu schreiben.
    Ich habe bereits ein laufendes, was im groben alle Daten welche die WetterApp erstellt auf einem USB-Stick sichert.
    Das Problem ist bei mir, das ich noch so meine Schwierigkeiten bzgl der Klassenaufteilung und des OOP habe. Oft erscheint mit das soviel "unnützen" Code.

    Soweit so gut. Ich habe nun eine Anforderungsanalyse (hängt als pdf an ) geschrieben und einen kleinen Teil begonnen zu schreiben.
    Habe den alten Code entfernt.
    Bilder
    • backuptool.jpg

      75,89 kB, 593×545, 95 mal angesehen
    Dateien
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Amelie“ ()

    Amelie schrieb:

    Oft erscheint mit das soviel "unnützen" Code.

    Was verstehst Du darunter?

    Ich schlage vor, dass Du nicht nur das Laufwerk auswählst sondern gleich jeweils einen Ordner für die Quelle und das Ziel auswählen lässt. (z.B. FileBrowserDialog)
    Nach dem der User hier die Dinge definiert hat, solltest Du prüfen, dass die Ordner auch vorhanden sind, bevor Du Deinen Export/Import startest.

    Auch solltest Du Dir überlegen, ob Du die Backup-Einstellungen irgendwo speicherst, um diese beim nächsten Start des Backups vordefinieren zu können.
    NB. Es ist doch schön, wenn man lesbare Namen vergibt. Siehe auch [VB.NET] Beispiele für guten und schlechten Code (Stil).
    jeweils einen Ordner für die Quelle und das Ziel auswählen lässt.

    Das wird hier gemacht... Wird sich auf dem Lappy nicht ändern.

    VB.NET-Quellcode

    1. ' Fixe Verzeichnisse die von dem Programm vorgegeben werden
    2. Public ReadOnly AppDatenMonat As String = "Wetterdaten"
    3. Public ReadOnly AppDatenJahr As String = "Wetterdaten\Jahresdaten"
    4. Public Property BackupDaten As String = "Wetterbackup"
    5. Public Property AlteBackup As String = "OldBackups"


    Du die Backup-Einstellungen irgendwo speicherst, um diese beim ...

    Wenn alles läuft, wir die CheckBox (C:\Wetterdaten) auf disebled gesetzt, da sich der Pfad ja nie ändert.
    Ebenso wird es bei der Checkbox nur USB-Stick weil der Lappy nur in freien Anschluss hat ;)

    Hoffe das ich dich richtig verstanden habe. ;)
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    @Amelie Wie wäre es mit dem SolutionExplorer vom @ErfinderDesRades?
    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!

    Amelie schrieb:

    Wenn alles läuft, wir die CheckBox (C:\Wetterdaten) auf disebled gesetzt, da sich der Pfad ja nie ändert.
    Ebenso wird es bei der Checkbox nur USB-Stick weil der Lappy nur in freien Anschluss hat


    Das ist für Deinen Anwendungsfall wohl die richtige Lösung.
    Aber was machst Du, wenn jemand anderes Dein Programm auch benutzen möchte und der folgendes Szenario hat. Die Sicherung soll über ein NAS auf einem Netzwerklaufwerk bzw. in OneDrive in einem Unterordner gespeichert werden.
    Du speicherts die Speicherordner nicht ab sondern gibst diese fest vor.
    Eine Möglichkeit ist es, die Dinge in den Anwendungseinstellungen (Settings.settings) abzulegen. Wenn Du da etwas eingibst gilt dies als Vorgabe für einen neue Installation, der Anwender kann über das Programm aber die Werte abändern.

    Du hast in den Settings zwei Einstellungen (Datenpfad und Sicherungspfad) angelegt.
    Beim Laden der Form liest Du diese aus und belegst die Bereich vor. (ControlXXX steht für das Steuerelement, das die Daten enthält)

    VB.NET-Quellcode

    1. ControlDaten.Text=My.Sett​ings.Datenpfad
    2. ControlSicherung.Text=My.Settings.Sicherungspfad


    Beim Schließen des Formulars oder beim Ausführen der Sicherung schreibst Du die Daten dann zurück in die Einstellungen.

    VB.NET-Quellcode

    1. ​My.Settings.Datenpfad=ControlDaten.Text
    2. My.Settings.Sicherungspfad=ControlSicherung.Text
    3. My.Settings.Save
    NB. Es ist doch schön, wenn man lesbare Namen vergibt. Siehe auch [VB.NET] Beispiele für guten und schlechten Code (Stil).
    @INOPIAE

    Ich war der Ansicht, das man dieses "My.Settings" nicht nutzen solle. Aber wenn das doch "erlaubt" ist könnte ich das nutzen.

    Habe nun meine Klassen und den Code erstmal überarbeitet, weil einige Fehler auftauchten.
    Hier lasse ich mir auch erstmal per Debug.WriteLine quasi "helfen". Hatte das bisher nie so richtig verstanden mit dem Debug...

    Wäre der Code soweit OK was Trennung etc betrifft?

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class LockTimer
    2. ' Objekte für den Timer
    3. Public endTime As DateTime
    4. Private countdownTimer As System.Windows.Forms.Timer
    5. Private lastBackupTime As DateTime = DateTime.MinValue
    6. Public Event Countdown As EventHandler
    7. Public Event CountdownComplete As EventHandler
    8. ''' <summary>
    9. ''' Initialisiert den Sperrtimer.
    10. ''' </summary>
    11. Public Sub New()
    12. InitializeBackupTimer()
    13. End Sub
    14. Private Sub InitializeBackupTimer()
    15. countdownTimer = New System.Windows.Forms.Timer()
    16. countdownTimer.Interval = 1000
    17. AddHandler countdownTimer.Tick, AddressOf TimerTick
    18. End Sub
    19. Private Sub TimerTick(sender As Object, e As EventArgs)
    20. Dim remainingTime As TimeSpan = endTime - DateTime.Now
    21. If remainingTime.TotalMilliseconds <= 0 Then
    22. countdownTimer.Stop()
    23. RaiseEvent CountdownComplete(Me, EventArgs.Empty)
    24. Else
    25. RaiseEvent Countdown(Me, EventArgs.Empty)
    26. End If
    27. End Sub
    28. Public Sub StartBackupTimer()
    29. ' Dauer des Countdowns einstellen
    30. endTime = DateTime.Now.AddMinutes(2)
    31. countdownTimer.Start()
    32. End Sub
    33. End Class


    VB.NET-Quellcode

    1. Public Class BackupManager
    2. Public Property _fileNameMonth As String = "Monatsdaten_"
    3. Public Property _fileNameYear As String = "Jahresdaten_"
    4. Private _directoryManager As DirectoryManager
    5. Private _backupFiles As List(Of BackupFile)
    6. Private _originalFiles As List(Of BackupFile)
    7. Public Sub New(directoryManager As DirectoryManager)
    8. _directoryManager = directoryManager
    9. _backupFiles = New List(Of BackupFile)()
    10. _originalFiles = New List(Of BackupFile)()
    11. End Sub
    12. Public Event BackupCompleted As EventHandler
    13. Public Event BackupFailed As EventHandler(Of Exception)
    14. Public Async Function BackupData(sourceDrive As String, targetDrive As String) As Task
    15. If String.IsNullOrEmpty(targetDrive) Then
    16. Throw New ArgumentException("Ungültiges Ziellaufwerk.")
    17. End If
    18. Debug.WriteLine("Backup Pfade in der Klasse" & sourceDrive, targetDrive)
    19. Dim targetPath As String = Path.Combine(targetDrive, _directoryManager.BackupDaten)
    20. If Not Directory.Exists(targetPath) Then
    21. Directory.CreateDirectory(targetPath)
    22. End If
    23. Dim monthDirectory As String = Path.Combine(sourceDrive, _directoryManager.AppDatenMonat)
    24. ValidateDirectory(monthDirectory, "Das Verzeichnis " & monthDirectory & " existiert nicht.")
    25. Dim yearDirectory As String = Path.Combine(sourceDrive, _directoryManager.AppDatenJahr)
    26. ValidateDirectory(yearDirectory, "Das Verzeichnis " & yearDirectory & " existiert nicht.")
    27. Dim monthFileName As String = _fileNameMonth & GenerateTimestamp() & ".zip"
    28. Dim monthFilePath As String = Path.Combine(targetPath, monthFileName)
    29. Dim xmlFiles As String() = Directory.GetFiles(monthDirectory, "*.xml")
    30. Dim tempDirectory As String = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString())
    31. Directory.CreateDirectory(tempDirectory)
    32. Try
    33. For Each xmlFile As String In xmlFiles
    34. Await Task.Run(Sub() File.Copy(xmlFile, Path.Combine(tempDirectory, Path.GetFileName(xmlFile))))
    35. Next
    36. Await Task.Run(Sub() ZipFile.CreateFromDirectory(tempDirectory, monthFilePath))
    37. Catch ex As Exception
    38. RaiseEvent BackupFailed(Me, ex)
    39. Debug.WriteLine("Fehler beim Erstellen des Backups: " & ex.Message)
    40. Throw
    41. Finally
    42. Directory.Delete(tempDirectory, recursive:=True)
    43. End Try
    44. Dim yearFileName As String = _fileNameYear & GenerateTimestamp() & ".zip"
    45. Dim yearFilePath As String = Path.Combine(targetPath, yearFileName)
    46. Try
    47. Await Task.Run(Sub() ZipFile.CreateFromDirectory(yearDirectory, yearFilePath))
    48. Catch ex As Exception
    49. RaiseEvent BackupFailed(Me, ex)
    50. Debug.WriteLine("Fehler beim Erstellen des Backups: " & ex.Message)
    51. Throw
    52. End Try
    53. RaiseEvent BackupCompleted(Me, EventArgs.Empty)
    54. End Function
    55. Private Sub ValidateDirectory(directoryPath As String, errorMessage As String)
    56. If Not Directory.Exists(directoryPath) Then
    57. RaiseEvent BackupFailed(Me, New DirectoryNotFoundException(errorMessage))
    58. Debug.WriteLine(errorMessage)
    59. Throw New DirectoryNotFoundException(errorMessage)
    60. End If
    61. End Sub
    62. Private Function GenerateTimestamp() As String
    63. Return DateTime.Now.ToString("dd_MM_yyyy_HH_mm")
    64. End Function
    65. End Class
    66. Public Class BackupFile
    67. Public Property FileName As String
    68. Public Property FilePath As String
    69. End Class


    VB.NET-Quellcode

    1. Public Class DirectoryManager
    2. ''' <summary>
    3. ''' Auflistung von benötigen Variablen etc.
    4. ''' </summary>
    5. Private _sourceDirectoryPath As String
    6. Private _targetDirectoryPath As String
    7. ' Fixe Verzeichnisse die von dem Programm vorgegeben werden
    8. Public ReadOnly AppDatenMonat As String = "Wetterdaten"
    9. Public ReadOnly AppDatenJahr As String = "Wetterdaten\Jahresdaten"
    10. Public Property BackupDaten As String = "Wetterbackup"
    11. Public Property AlteBackup As String = "OldBackups"
    12. Public Property FixDrive As String = "C:\"
    13. Public Property OnlyUSB As Boolean
    14. ''' <summary>
    15. ''' Events welche an Haupform gesendet werden
    16. ''' </summary>
    17. Public Event onDrives As EventHandler
    18. Public Event onMessage As EventHandler
    19. Public Event onError As EventHandler(Of Exception)
    20. Public Event SourcePathsChanged As EventHandler
    21. Public Event TargetPathsChanged As EventHandler
    22. ''' <summary>
    23. ''' Der Pfad zum Zielverzeichnis.
    24. ''' </summary>
    25. Public Property TargetDirectoryPath As String
    26. Get
    27. Return _targetDirectoryPath
    28. End Get
    29. Set(value As String)
    30. _targetDirectoryPath = value
    31. RaiseEvent TargetPathsChanged(Me, EventArgs.Empty)
    32. End Set
    33. End Property
    34. ''' <summary>
    35. ''' Der Pfad zum Quellverzeichnis.
    36. ''' </summary>
    37. Public Property SourceDirectoryPath As String
    38. Get
    39. Return _sourceDirectoryPath
    40. End Get
    41. Set(value As String)
    42. _sourceDirectoryPath = value
    43. RaiseEvent SourcePathsChanged(Me, EventArgs.Empty)
    44. End Set
    45. End Property
    46. ''' <summary>
    47. ''' Ruft eine Liste der verfügbaren Laufwerke basierend auf den angegebenen Kriterien ab.
    48. ''' </summary>
    49. Public Function GetDriveList(ByVal onlyUSB As Boolean) As List(Of String)
    50. Dim driveList As New List(Of String)()
    51. Try
    52. Dim drives As DriveInfo() = DriveInfo.GetDrives()
    53. For Each drive As DriveInfo In drives
    54. If onlyUSB AndAlso drive.DriveType = DriveType.Removable Then
    55. Dim displayName As String = drive.Name
    56. driveList.Add(displayName)
    57. ElseIf Not onlyUSB Then
    58. Dim displayName As String = drive.Name
    59. driveList.Add(displayName)
    60. End If
    61. Next
    62. Catch ex As Exception
    63. RaiseEvent onError(Me, ex)
    64. End Try
    65. Return driveList
    66. End Function
    67. End Class


    VB.NET-Quellcode

    1. Public Class frmMain
    2. Private WithEvents _directoryManager As New DirectoryManager()
    3. Private WithEvents _backupManager As BackupManager
    4. Private WithEvents _xmlZipManager As XMLZipManger
    5. Private WithEvents _lockTimer As New LockTimer
    6. Public Sub New()
    7. InitializeComponent()
    8. ' Erstellen der Instanz von BackupManager mit Verweis auf den DirectoryManager
    9. _backupManager = New BackupManager(_directoryManager)
    10. _xmlZipManager = New XMLZipManger(_directoryManager)
    11. End Sub
    12. Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    13. InitialeSource()
    14. InitialeTarget()
    15. End Sub
    16. #Region "Combo-Check-Target"
    17. Private Sub InitialeTarget()
    18. If chkUSB.Checked Then
    19. cmbTargetdrive.DataSource = _directoryManager.GetDriveList(True)
    20. Else
    21. cmbTargetdrive.DataSource = _directoryManager.GetDriveList(False)
    22. End If
    23. End Sub
    24. Private Sub chkUSB_CheckedChanged(sender As Object, e As EventArgs) Handles chkUSB.CheckedChanged
    25. _directoryManager.OnlyUSB = chkUSB.Checked
    26. If chkUSB.Checked Then
    27. cmbTargetdrive.DataSource = _directoryManager.GetDriveList(True)
    28. cmbTargetdrive.SelectedIndex = -1
    29. Else
    30. cmbTargetdrive.DataSource = _directoryManager.GetDriveList(False)
    31. cmbTargetdrive.SelectedIndex = -1
    32. End If
    33. End Sub
    34. Private Sub cmbTargetdrive_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbTargetdrive.SelectedIndexChanged
    35. If cmbTargetdrive.SelectedItem IsNot Nothing Then
    36. Dim selectedDriveLetter As String = cmbTargetdrive.SelectedItem.ToString()
    37. _directoryManager.TargetDirectoryPath = selectedDriveLetter
    38. Dim listFiles As New XMLZipManger(_directoryManager)
    39. End If
    40. End Sub
    41. Private Sub TargetDirectoryChanges(sender As Object, e As EventArgs) Handles _directoryManager.TargetPathsChanged
    42. Debug.WriteLine("TargetPath: " & _directoryManager.TargetDirectoryPath)
    43. End Sub
    44. #End Region
    45. #Region "Combo-Check-Source"
    46. Private Sub InitialeSource()
    47. cmbSourceDrive.Items.Clear()
    48. Dim drives As List(Of String) = _directoryManager.GetDriveList(False)
    49. For Each drive As String In drives
    50. cmbSourceDrive.Items.Add(drive)
    51. Next
    52. End Sub
    53. Private Sub chkFixSourcePath_CheckedChanged(sender As Object, e As EventArgs) Handles chkFixSourcePath.CheckedChanged
    54. If chkFixSourcePath.Checked Then
    55. cmbSourceDrive.Items.Clear()
    56. cmbSourceDrive.Items.Add(_directoryManager.FixDrive)
    57. cmbSourceDrive.SelectedItem = _directoryManager.FixDrive
    58. _directoryManager.SourceDirectoryPath = _directoryManager.FixDrive
    59. Else
    60. InitialeSource()
    61. End If
    62. End Sub
    63. Private Sub cmbSourceDrive_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbSourceDrive.SelectedIndexChanged
    64. Dim selectedDrive As String = cmbSourceDrive.SelectedItem.ToString()
    65. _directoryManager.SourceDirectoryPath = selectedDrive
    66. Dim listFiles As New XMLZipManger(_directoryManager)
    67. End Sub
    68. Private Sub SourceDirectoryChanges(sender As Object, e As EventArgs) Handles _directoryManager.SourcePathsChanged
    69. Debug.WriteLine("SourcePath: " & _directoryManager.SourceDirectoryPath)
    70. End Sub
    71. #End Region
    72. ''' <summary>
    73. ''' Startet das Backup der XML-Dateien.
    74. ''' Aktualisiert die Anzeigen über ein Label.
    75. ''' </summary>
    76. Private Async Sub btnBackupStart_Click(sender As Object, e As EventArgs) Handles btnBackupStart.Click
    77. Try
    78. Debug.WriteLine("Backup Pfade MainForm " & _directoryManager.SourceDirectoryPath, "--" & _directoryManager.TargetDirectoryPath)
    79. ' Stop
    80. Await _backupManager.BackupData(_directoryManager.SourceDirectoryPath, _directoryManager.TargetDirectoryPath)
    81. ' Der Code, bei dem die NullReferenceException auftritt
    82. Catch ex As NullReferenceException
    83. ' Stack-Trace drucken
    84. Debug.WriteLine("NullReferenceException aufgetreten:")
    85. Debug.WriteLine(ex.StackTrace)
    86. End Try
    87. End Sub
    88. Private Sub BackupManager_BackupCompleted(sender As Object, e As EventArgs) Handles _backupManager.BackupCompleted
    89. ' Backup abgeschlossen
    90. Debug.WriteLine("Backup erfolgreich abgeschlossen!")
    91. lblEventInfos.Visible = True
    92. lblEventInfos.Text = "Backup erfolgreich abgeschlossen!"
    93. btnBackupStart.Enabled = False
    94. ' Den SperrTimer starten
    95. _lockTimer.StartBackupTimer()
    96. End Sub
    97. Private Sub BackupManager_BackupFailed(sender As Object, e As Exception) Handles _backupManager.BackupFailed
    98. ' Backup fehlgeschlagen
    99. Debug.WriteLine("Fehler beim Backup: " & e.Message)
    100. lblEventInfos.Visible = True
    101. lblEventInfos.Text = "Fehler beim Backup: " & e.Message
    102. End Sub
    103. Private Sub lockTimer_CountdownTimer(sender As Object, e As EventArgs) Handles _lockTimer.Countdown
    104. ' Coundownzähler
    105. Dim remainingTime As TimeSpan = _lockTimer.endTime - DateTime.Now
    106. lblCountdown.Text = "Wartezeit beträgt noch:" '& remainingTime.ToString("mm\:ss")
    107. btnBackupStart.Text = remainingTime.ToString("mm\:ss")
    108. End Sub
    109. Private Sub lockTimer_CountdownComplete(sender As Object, e As EventArgs) Handles _lockTimer.CountdownComplete
    110. ' Wird aufgerufen, wenn der Countdown abgelaufen ist
    111. btnBackupStart.Enabled = True
    112. btnBackupStart.Text = "Backup starten"
    113. lblCountdown.Text = ""
    114. End Sub
    115. End Class

    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:

    Das ist nix für mein Opa
    Dann mach da was für Deinen Opa draus. ;)
    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!
    Hier einige Anmerkungen zum Code:

    Das mit dem Debug.Print ist eine gut Idee. Man sollte im fertigen Projekt dieses auch wieder löschen, es sein denn man setzt es zur Code-Überwachung ein.

    Mache doch für die Textausgaben zum Anwender z.B. statt:

    VB.NET-Quellcode

    1. "Das Verzeichnis " & yearDirectory & " existiert nicht."

    dies

    VB.NET-Quellcode

    1. String.Format("Das Verzeichnis {0} existiert nicht.", yearDirectory)


    Wenn Du mehrere Variablen verknüpfen willst, nimmst Du innerhalb des Strings jeweils ein {x} wobei x für die Position der Variablen hinter dem Komma steht.
    Der Vorteil kommt spätestens dann zum Tragen, wenn man die Software mehrsprachig anlegen möchte. Dann wird nur der String übersetzt. Je nach Sprache muss man dann aber den Basissyntax umstellen, was mit verketteten Strings (&) nicht so ohne weiteres geht.

    Was hast Du in der Class LockTimer mit der Varibale lastBackupTime vor?

    Mache doch aus der Class BackupFile in der Class

    VB.NET-Quellcode

    1. Public Class BackupFile
    2. Public Property FileName As String
    3. Public Property FilePath As String
    4. End Class

    eine Structure

    VB.NET-Quellcode

    1. Public Class BackupManager
    2. Public Property _fileNameMonth As String = "Monatsdaten_"
    3. Public Property _fileNameYear As String = "Jahresdaten_"
    4. Public Structure BackupFile
    5. Dim FileName As String
    6. Dim FilePath As String
    7. End Structure
    8. ...
    NB. Es ist doch schön, wenn man lesbare Namen vergibt. Siehe auch [VB.NET] Beispiele für guten und schlechten Code (Stil).
    @INOPIAE
    Die Varibale lastBackupTime und Public Class BackupManager gibt es nicht mehr. Dachte erst ich bräuchte die noch.

    Das mit den Debug.Writeline wollte ich noch fragen ob man die alle wieder löschen muss.

    Bin jetzt die verschiedensten Szenarien am Testen ob der Backupteil richtig arbeitet.

    @RodFromGermany
    Dann mach da was für Deinen Opa draus ..... Ich denke eher, dafür reicht`s bei mir noch nicht
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:


    Das mit den Debug.Writeline wollte ich noch fragen ob man die alle wieder löschen muss.

    Kannst auch drin lassen.

    VB.NET-Quellcode

    1. #If DEBUG Then
    2. Debug.Writeline("bla")
    3. #End If


    In der Debug Version wird WriteLine ausgeführt, ist aber in der Release Version nicht mehr vorhanden.
    Aktuelles Projekt: Z80 Disassembler für Schneider/Amstrad CPC :love:
    Eine Frage an alle bzgl. Laufwerksbuchstaben.

    Ich habe an meinem alten PC ( Windows 7-64Bit ) zwei USB-Anschlüsse. Egal, welchen ich benutze, bekommt der USB-Stick immer den selben Laufwerkbuchstaben.
    Ist das immer so? :?: Wenn ja wäre das für mein BackUp-Tool (für Opa :) ) ja super.

    Dann könnte ich das schon beim Start immer aktiviert lassen, denn hier werden dann gleich die richtigen Daten gelesen, wenn ich den BackUp USB-Stick einstecke.

    VB.NET-Quellcode

    1. #Region "Combo-Check-TargetLaufwerk"
    2. ''' <summary>
    3. ''' Initialisiert die Einstellungen der Ziellaufwerke.
    4. ''' </summary>
    5. Private Sub chkUSB_CheckedChanged(sender As Object, e As EventArgs) Handles chkUSB.CheckedChanged
    6. _directoryManager.OnlyUSB = chkUSB.Checked
    7. If chkUSB.Checked Then
    8. cmbTargetdrive.DataSource = _directoryManager.GetDriveList(True)
    9. cmbTargetdrive.SelectedIndex = -1
    10. Else
    11. cmbTargetdrive.DataSource = _directoryManager.GetDriveList(False)
    12. cmbTargetdrive.SelectedIndex = -1
    13. End If
    14. End Sub
    15. Private Sub cmbTargetdrive_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbTargetdrive.SelectedIndexChanged
    16. If cmbTargetdrive.SelectedItem IsNot Nothing Then
    17. Dim selectedDriveLetter As String = cmbTargetdrive.SelectedItem.ToString()
    18. _directoryManager.TargetDirectoryPath = selectedDriveLetter
    19. Dim listFiles As New XMLZipManger(_directoryManager)
    20. lblNewBackups.Focus()
    21. DisplayBackupFiles(listFiles)
    22. End If
    23. End Sub
    24. Private Sub TargetDirectoryChanges(sender As Object, e As EventArgs) Handles _directoryManager.TargetPathsChanged
    25. Debug.WriteLine("TargetPath: " & _directoryManager.TargetDirectoryPath)
    26. ' Anzeigen des Zielverzeichnispfads auf dem entsprechenden Label
    27. lblTargetpath.Text = "Ziel: " & _directoryManager.TargetDirectoryPath & _directoryManager.BackupDaten
    28. End Sub
    29. #End Region
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    Bezüglich dem Debug.WriteLine (und den anderen Debug.XXX Methoden): Man kann diese sowohl im Code lassen, als auch ohne den #if DEBUG / #endif Guards schreiben. Der Compiler entfernt diese Calls automatisch im Release Build, weil die Methoden mit dem Conditional("DEBUG") Attribut geflagged sind.

    Das ganze kann man ganz gut hier sehen (linke Seite euer Code, rechte Seite der finale, kompilierte Code im Debug/Release Mode):

    - Debug: sharplab.io/#v2:CYLg1APgsAUAAg…IpvzAUsz6VADcdPgAvrDZQA==
    - Release: sharplab.io/#v2:D4WAUAAgzABBBM…GH1OHxFaTRIAbgpMAF9wNKA==

    Sprich, schreibt sie, wenn sie sinnvoll sind, einfach rein und lasst sie im Zweifel stehen, wenn ihr glaubt, dass sie in der Zukunft noch wichtig sein könnten. Mit #if DEBUG / #endif macht man die Codestellen dann nur unnötig unleserlich und länger.
    Hallo

    Also mein BackUp läuft nun so wie ich es mir vorstellte und ich denke so wie ich es in der Aufgabenbeschreibung verfasst habe.

    Was ich nun brauche: Eine konkrete Hilfe wie ich das mit dem "RESTORE" machen muss?
    Habe damit Null Erfahrungen.
    Einfach einen Eintrag auswählen und dann??
    Zip öffnen und die Daten im Verzeichnis überschreiben?

    EDIT um: 15:37 Code hinzugefügt
    Also das habe ich nun. Noch alles sehr "wild" etc.. aber es tut schonmal was.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class RestoreManager
    2. Private _directoryManager As DirectoryManager
    3. Public Sub New(directoryManager As DirectoryManager)
    4. _directoryManager = directoryManager
    5. End Sub
    6. Public Event RestoreCompleted As EventHandler
    7. Public Event RestoreFailed As EventHandler(Of Exception)
    8. Private Sub RestoreZipFiles(backupName As String)
    9. Debug.WriteLine("Test2 backupName: " & backupName)
    10. Dim selectedZipFile As String = Path.Combine(_directoryManager.SourceDirectoryPath, backupName)
    11. ' Überprüfen, ob die ausgewählte Zip-Datei existiert
    12. If File.Exists(selectedZipFile) Then
    13. ' Verzeichnis erstellen, in das die Daten extrahiert werden sollen
    14. Dim targetDirectory As String = GetTargetDirectory(backupName)
    15. Directory.CreateDirectory(targetDirectory)
    16. ' Zip-Datei extrahieren und mögliche Überschreibungen vermeiden
    17. Using archive As ZipArchive = ZipFile.OpenRead(selectedZipFile)
    18. For Each entry As ZipArchiveEntry In archive.Entries
    19. Dim entryPath As String = Path.Combine(targetDirectory, entry.FullName)
    20. ' Überprüfen, ob die Datei bereits im Zielverzeichnis existiert
    21. If File.Exists(entryPath) Then
    22. Dim dialogResult As DialogResult = MessageBox.Show("Die Datei '" & entryPath & "' existiert bereits im Zielverzeichnis. Möchten Sie die Datei überschreiben?", "Überschreiben bestätigen", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
    23. If dialogResult = dialogResult.No Then
    24. ' Überspringen, wenn die Datei nicht überschrieben werden soll
    25. Continue For
    26. End If
    27. End If
    28. ' Datei extrahieren
    29. entry.ExtractToFile(entryPath, True)
    30. Next
    31. End Using
    32. Debug.WriteLine("Zip-Datei erfolgreich extrahiert.")
    33. ' Beispiel: Alle Dateien im Zielverzeichnis anzeigen
    34. Dim filesInTargetDirectory As String() = Directory.GetFiles(targetDirectory)
    35. For Each file In filesInTargetDirectory
    36. Debug.WriteLine("Datei im Zielverzeichnis: " & file)
    37. Next
    38. Else
    39. Debug.WriteLine("Die ausgewählte Zip-Datei existiert nicht.")
    40. End If
    41. End Sub
    42. Private Function GetTargetDirectory(backupName As String) As String
    43. Dim fileName As String = Path.GetFileNameWithoutExtension(backupName)
    44. ' Auswahl ob Monats oder Jahresdaten ...
    45. If fileName.StartsWith("Monatsdaten") Then
    46. Return Path.Combine(_directoryManager.SourceDirectoryPath, _directoryManager.AppDatenMonat)
    47. ElseIf fileName.StartsWith("Jahresdaten") Then
    48. Return Path.Combine(_directoryManager.SourceDirectoryPath, _directoryManager.AppDatenJahr)
    49. Else
    50. ' Standardzielverzeichnis, wenn der Dateiname nicht erkannt wird
    51. Return _directoryManager.SourceDirectoryPath
    52. End If
    53. End Function
    54. End Class

    Bilder
    • backuptool.jpg

      208,08 kB, 598×510, 69 mal angesehen
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Amelie“ ()

    Mal ein zwei Szenarien:
    • Was soll passieren, wenn die letzte Sicherung zurück gespielt wird?
    • Was soll passieren, wenn ich im März die Sicherung vom Februar zurückschreibe?

    Wenn ich mir Dein Backup Konzept anschaue, musst Du immer die Monatsdaten und die dazugehörigen Jahresdaten zurückschreiben. Wäre es nicht besser alle Dateien (Monats- und Jahresdaten) in eine ZIP-Datei zu packen?

    PS:
    Hast Du Dich schon mal mit den Themen Test-Driven-Development und Unit-Tests auseinander gesetzt? Falls Du dazu Fragen hast, mache ein neues Thema uf.
    NB. Es ist doch schön, wenn man lesbare Namen vergibt. Siehe auch [VB.NET] Beispiele für guten und schlechten Code (Stil).

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „INOPIAE“ ()

    @INOPIAE

    wenn die letzte Sicherung zurück gespielt wird?

    Eigentlich braucht man da immer nur die Letzte Sicherung zum Wiederherstellen. Weil da sind ja immer alle eingetragenen Werte enthalten.
    Das BackUp soll ja nur dazu dienen, wenn mal die Festplatte, das Windows kaputt geht usw... :!:
    Deswegen habe ich schon gesagt, das Opa mindestens an jedem 1ten des Monats eine Sicherung machen soll. :D

    (Monats- und Jahresdaten) in eine ZIP-Datei zu packen?

    Das ist mir auch schon aufgefallen, als ich die Anforderung schrieb aber nicht. ;(

    ​Themen Test-Driven-Development und Unit-Tests

    Nein. Bisher habe ich eigentlich nur so vor mich hin "programmiert" ... naja programmieren kann man das nicht nennen.

    Mit der WetterApp und dem BackUp hier habe ich erstmal eine Anforderung versucht zu schreiben usw...
    Vor allem das mit der strickten Trennung von GUI und Ablauf usw...

    Deswegen wäre eine Hilfe gut, auf was ich alles achten muss usw...
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:

    ​Themen Test-Driven-Development und Unit-Tests

    Bei dem Test-Driven-Development werden zunächst für alle öffentlichen Methoden einer Klasse UnitTests angelegt. Diese müssen alle durchlaufen, bevor man weiter macht. Dabei sollte auch auf fehlerhaftes Verhalten getestet werden.
    Später bei der Entwicklung, lässt man dann immer alle Test wieder durchlaufen, ob sie immer noch ohne Fehler durchlaufen, es kann ja durch aus sein, dass man einen Änderung in einer Klasse nicht sauber in einer anderen Klasse berücksichtigt hat.
    NB. Es ist doch schön, wenn man lesbare Namen vergibt. Siehe auch [VB.NET] Beispiele für guten und schlechten Code (Stil).
    Zur Präzisierung eine Ergänzung, wie ich TDD verstanden habe:

    Man erzeugt einen Test, der scheitert, macht nur genauso viel, dass der Test nicht mehr scheitert, führt alle vorhandenen Tests aus, um zu sehen, ob alle bisher geschriebenen Tests noch laufen. Wenn ja, verbessert man den Code und schreibt den nächsten Test. Wenn nicht: Fehler finden - er kann nicht weit gekommen sein ;)

    Die Testumgebung ist in einfachster Form ein Programm, welches die zu entwickelnde Methode M und all die Testmethoden enthält und dann nur alle Tests aufruft. Es gibt aber bei den Projektvorlagen auf Testprojekte, die den Test- und Entwicklungsprozess effizienter durchführen.

    Jeder Schritt (red (Test scheitert), green (Test hat nach Umbau von M Erfolg), refactor (Code verbessern und zur Sicherheit nochmal die Tests durchlaufen lassen)) dauert normalerweise nur wenige Sekunden, weil man M in klein(st)en Schritten ändert.

    Man will eine Methode M schreiben, die etwas bestimmtes macht, als Beispiel: einen String rückwärts ausgeben.
    • Man schreibt einen Test T1, also eine kleine Funktion, die eine zu erzeugende Methode M aufruft. T1 scheitert, weil M nicht existiert: M()
    • Man schreibt die Sub M, und zwar nur den Methodenrumpf, also soviel, dass T1 nicht mehr scheitert.
    • Man schreibt einen weiteren Test T2, der ein Sollmerkmal von M überprüft. Also z.B. Übergabe eines String-Parameters. T2 scheitert, weil M keine Parameter entgegennimmt: M("")
    • Man erweitert M um den String-Parameter, sodass T2 nicht mehr scheitert.
    • Man schreibt einen weiteren Test T3, der ein weiteres Sollmerkmal von M überprüft. Also z.B. dass ein String zurückgegeben wird. T3 scheitert, weil M eine Sub ist und keine String-Function: If M("") <> "" Then SchlageAlarm
    • Man ändert M von Sub auf Function und gibt als Rückgabeparameter String an. Den Fehler wegen fehlendem Rückgabewert beseitigt man so einfach wie möglich, nicht so sinnvoll wie möglich: Return Nothing
    • Man schreibt einen weiteren Test T4, der ein weiteres Sollmerkmal von M überprüft. Also z.B. dass ein fester String "Test" umgekehrt zurückgegeben wird. T4 scheitert, weil M ja Nothing zurückgibt: If M("Test") <> "tesT" Then SchlageAlarm
    • Man ändert die M-Codezeite auf Return "tesT", damit T4 Erfolg hat.
    • Man schreibt einen weiteren Test T5, der das letzte Sollmerkmal von M anders überprüft. Also z.B., dass ein anderer fester String "Foo" umgekehrt zurückgegeben wird. T4 scheitert, weil M ja "tesT" zurückgibt.
    • Jetzt ist der erste Schritt, wo man etwas mehr tun muss, und das erste Mal zum Nachdenken gezwungen wird. Ab hier beginnt der Prozess der erfindungsreichen Code-Entwickler :)
    Werden weitere Sollmerkmale benötigt, werden diese Schritt für Schritt (red-green-refactor) ergänzt. Weitere Tests, vor allem provokative wie Grenzfälle ("dreh mir String.Empty oder Nothing um") sollten immer mit dazu gehören.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    @VaporiZed @INOPIAE

    Ich weiß noch nicht genau ob ich das letzte von euch verstanden habe. ?(

    Als ich z.B. mit dem BackUpSystem hier angefangen hatte, habe ich es so gemacht.

    Ein Form mit nur einem Button. Dann nur eine Sub oder Funktion begonnen zu schreiben. Z.B. das:

    Erst als Sub ...

    VB.NET-Quellcode

    1. Public Sub BackupData(sourceDrive As String, targetDrive As String)
    2. Debug.WriteLine("sourceDrive: " & sourceDrive)
    3. Debug.WriteLine("targetDrive: " & targetDrive)

    Als die ganze Sub dann lief zur Function mit Async umgebaut

    VB.NET-Quellcode

    1. Public Async Function BackupData(sourceDrive As String, targetDrive As String) As Task
    2. Debug.WriteLine("sourceDrive: " & sourceDrive)
    3. Debug.WriteLine("targetDrive: " & targetDrive)

    Das habe mich mir dann immer mit den ganzen Debug.Writelines ausgeben lassen.
    Alles immer schrittweise aufgebaut. Immer nur dann ein neues Steuerelement auf das Form gezogen, wenn es unbedingt nötig war.

    Ich muss auch zugeben, das ich da oft den Überblick verloren hatte. :S
    Besonders das mit der Klassenaufteilung..
    Bilder
    • Unbenannt-1.jpg

      129,35 kB, 825×431, 54 mal angesehen
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:

    Ich weiß noch nicht genau ob ich das letzte von euch verstanden habe.

    Gib mir mal einige Tage Zeit. Ich schreib gerade mal ein Tutorial zu dem Thema Unit Test.
    NB. Es ist doch schön, wenn man lesbare Namen vergibt. Siehe auch [VB.NET] Beispiele für guten und schlechten Code (Stil).

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „INOPIAE“ ()