Aller au menu - Aller au contenu

Icône TP : ZBackup

Avatar
Mise à jour : 13/12/2010
Difficulté : Intermédiaire Intermédiaire Creative Commons BY-NC-SA
23 410 visites depuis 7 jours, dont 236 sur ce chapitre classé 14/786
Eh bien chers amis zéros, on va attaquer un TP de taille.

Ce TP aura pour but de nous faire développer un programme (nommé ZBackup par mes soins) qui aura pour but d'effectuer des sauvegardes périodiques de dossiers spécifiés.

Je ne vous en dis pas plus, on attaque tout de suite.
Sommaire du chapitre :
Icône du chapitre
Chapitre précédent Sommaire Chapitre suivant

Le cahier des charges

Eh bien c'est parti pour le cahier des charges !

En premier lieu je vais vous décrire ce que notre programme sera susceptible de faire.

Donc, tout d'abord ce programme est un programme d'auto backup, autrement dit : sauvegarde automatique.

Ce programme sera capable de sauvegarder périodiquement un ou des dossiers que nous spécifierons dans une liste.

Pour commencer nous n'allons pas chercher bien loin : nous allons juste créer un répertoire dans lequel nous entasserons nos sauvegardes (répertoire spécifié par l'utilisateur). Essayez de ranger et de trier les différentes sauvegardes, pourquoi pas avec la date et l'heure.

Attention à ce point, les dossiers n'ont pas de fonction permettant leur copie, vous allez devoir copier les fichiers individuellement, essayez de trouver un algorithme, servez-vous de notre mini-tp sur l'arborescence.


Je vous laisse libre court à votre imagination, à vous de voir si une seconde fenêtre est préférable pour spécifier la configuration, etc ...

En parlant de configuration, après nos deux chapitres sur les fichiers, j'aimerais que vous sauvegardiez les paramètres de configuration de ce petit programme dans un fichier .ini. Je vous laisse également choisir la structure qu'aura ce fichier, les choses que vous allez avoir à insérer dedans, etc ...

Pour le choix des dossiers, je ne vous en avais pas parlés avant mais un petit module très pratique existe : le FolderBrowserDialog.

Dans la boite à outils, section boites de dialogue. Ce module ouvre une boite de dialogue, demandant à l'utilisateur de sélectionner un dossier. Il a également la possibilité d'en créer un par la même occasion. Vous pouvez récupérer le dossier sélectionné avec FolderBrowserDialog.SelectedPathFolderBrowserDialog est le nom de votre contrôle.

Pour ce qui est de la liste des dossiers à sauvegarder, vous pouvez les insérer dans une listbox ou une textbox multilignes, au choix.

Pour le reste, je vous laisser agrémenter au choix et selon vos goûts..

Je dois dire que vous avez toutes les compétences et les méthodes de réflexion (savoir trouver les propriétés qui vous seront utiles) requise. Essayez de ne pas vous décourager trop rapidement et ne pas aller trop vite à la correction.

Eh bien, amis zéros, au travail !

Correction

Alors, en espérant que vous avez donnés le meilleur de vous même.

Commençons par mon interface et par les fonctionnalités que mon programme contient.

Image utilisateur


Comme vous le voyez, j'ai une listbox qui me permet de lister les répertoires dont je veux la sauvegarde.
Viens ensuite un bouton d'ajout et de suppression des répertoires, l'ajout se fait par FolderBrowserDialog, la suppression par lignes sélectionnées dans la listbox.
Un petit menu de configuration dans lequel on spécifie le dossier où placer les sauvegardes. Lors du clic sur la textbox un folderbrowserdialog s'ouvre et c'est sa sélection qui remplira la textbox.
Des NumericUpDown (un contrôle) permettant de spécifier un nombre avec le clavier ou grâce à des boutons haut et bas.

Puis un bouton pour enregistrer la configuration et un second pour effectuer une sauvegarde manuelle.

Bon je vais vous montrer le code tout de suite, on va développer section par section.

Secret (cliquez pour afficher)

Code : VB.NET
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
Imports System.IO

Public Class ZBackup

    'Définit les constantes
    Const FichierIni As String = "Zbackup.ini"
    Const LignesFichierIni As Integer = 6
    Const CleSavePath As String = "SavePath"
    Const CleTempSave As String = "TempSave"
    Const CleNbSaves As String = "NbSaves"
    Const ClePaths As String = "Paths"

    Private Sub ZBackup_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        'Configure le timer
        Me.TIM_SAVE.Interval = Me.NUM_SAVETIME.Value * 3600000 'Convertir une heure une milisecondes
        Me.TIM_SAVE.Enabled = True

        'Recupère la configuration enregistrée
        If RecupereInfosFichierIni() Then
            'Effectue d'office une sauvegarde
            Sauvegarde()
        End If

    End Sub

#Region "Interface"

    Private Sub TXT_SAVEPATH_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TXT_SAVEPATH.Click

        'Ajoute la ligne seulement si un dossier a été selectioné dans le dialogue
        If Me.BD_DOSSIER.ShowDialog() Then
            Me.TXT_SAVEPATH.Text = Me.BD_DOSSIER.SelectedPath
        End If

    End Sub

    Private Sub BT_AJOUT_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BT_AJOUT.Click

        'Ajoute la ligne seulement si un dossier a été selectionné dans le dialogue
        If Me.BD_DOSSIER.ShowDialog Then
            Me.LB_PATHSASAVE.Items.Add(Me.BD_DOSSIER.SelectedPath)
        End If

    End Sub

    Private Sub BT_SUPPR_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BT_SUPPR.Click

        'Vérifie si une ligne est sélectionnée dans la listbox
        If Not Me.LB_PATHSASAVE.SelectedItem Is Nothing Then
            Me.LB_PATHSASAVE.Items.Remove(Me.LB_PATHSASAVE.SelectedItem)
        Else
            MsgBox("Selectionnez un path à supprimer")
        End If

    End Sub

    Private Sub BT_SAVECFG_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BT_SAVECFG.Click
        SauvegardeFichierIni()
    End Sub

    Private Sub TIM_SAVE_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TIM_SAVE.Tick
        'Sauvegarde avec le timer
        Sauvegarde()
    End Sub

    Private Sub BT_MANUSAVE_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BT_MANUSAVE.Click
        'Sauvegarde manuelle
        Sauvegarde()
    End Sub

#End Region

#Region "FichierIni"

    Sub SauvegardeFichierIni()
        'Verification sur le path de sauvegarde
        If Me.TXT_SAVEPATH.Text = "" Then
            MsgBox("Veuillez selectionner un path de sauvegarde")
        ElseIf Not Directory.Exists(Me.TXT_SAVEPATH.Text) Then
            MsgBox("Path de sauvegarde invalide")
        Else
            'La fonction recrée le fichier quoi qu'il arrive
            File.WriteAllLines(FichierIni, CreeStructureFichierIni(Me.TXT_SAVEPATH.Text, Me.NUM_SAVETIME.Value, Me.NUM_NBSAVE.Value, Me.LB_PATHSASAVE.Items))
        End If
    End Sub

    Function CreeStructureFichierIni(ByVal SavePath As String, ByVal TempsSave As Integer, ByVal Nbsaves As Integer, ByVal PathsASave As ListBox.ObjectCollection) As String()

        'Crée un tableau du nombre de lignes requises
        Dim FichierIni(LignesFichierIni + PathsASave.Count) As String
        'Replit la structure du fichier ini
        FichierIni(0) = ";Fichier de configuration du Zbackup"
        FichierIni(1) = "[configuration]"
        FichierIni(2) = CleSavePath & "=" & SavePath
        FichierIni(3) = CleTempSave & "=" & TempsSave
        FichierIni(4) = CleNbSaves & "=" & Nbsaves
        FichierIni(5) = ""
        FichierIni(6) = "[paths]"
        'Rempli dynamiquement les paths souhaités
        Dim Compteur As Integer = LignesFichierIni
        For Each Path As String In PathsASave
            Compteur += 1
            FichierIni(Compteur) = ClePaths & Compteur - LignesFichierIni & "=" & Path
        Next

        Return FichierIni

    End Function

    Function RecupereCleFichierIni(ByVal Cle As String) As String

        For Each Ligne As String In File.ReadAllLines(FichierIni)
            'Découpe la ligne au niveau de "=" (s'il existe), 
            'compare la premiere partie de la ligne (soit la clé)
            If Ligne.Split("=")(0) = Cle Then
                'Recupère la seconde partie de la ligne (soit la valeur)
                Return Ligne.Split("=")(1)
            End If
        Next
        'Sinon ne retourne rien
        Return ""

    End Function

    Function RecupereInfosFichierIni() As Boolean

        'Verification de la présence du .ini
        If File.Exists(FichierIni) Then
            'Recuperation
            Dim SavePath As String = RecupereCleFichierIni(CleSavePath)
            Dim TempSAve As String = RecupereCleFichierIni(CleTempSave)
            Dim NbSaves As String = RecupereCleFichierIni(CleNbSaves)
            Dim Paths(100) As String
            Dim i As Integer = 0 '0 car le premier path est à 1 et on incrémente avant
            Do
                i += 1
                Paths(i - 1) = RecupereCleFichierIni(ClePaths & i)
            Loop While Paths(i - 1) <> ""
            'Donc nombre de paths valides : i-1

            'Verification
            If (SavePath <> "") And (TempSAve <> "") And (NbSaves <> "") And (i - 1 > 0) Then
                'Attribution
                Me.TXT_SAVEPATH.Text = SavePath
                Me.NUM_NBSAVE.Value = NbSaves
                Me.NUM_SAVETIME.Value = TempSAve
                'Nettoie le LB puis le remplit
                Me.LB_PATHSASAVE.Items.Clear()
                For j As Integer = 0 To i - 1
                    Me.LB_PATHSASAVE.Items.Add(Paths(j))
                Next
            Else
                'Sinon notification
                MsgBox("Le fichier " & FichierIni & " est corrompu, utilisation des paramètres par défaut")
                Return False
            End If
        Else
            'Sinon notification
            MsgBox("Le fichier " & FichierIni & " n'a pas été trouvé, utilisation des paramètres par défaut")
            Return False
        End If

        Return True

    End Function

#End Region

#Region "Sauvegarde"

    Sub Sauvegarde()

        'Vérifie les paramètres
        If Directory.Exists(Me.TXT_SAVEPATH.Text) Then
            'Vérifie le nombre de sauvegardes
            'Supprime la plus vieille si limite atteinte
            NettoieNbSaves()

            'Si le dernier caractère de la chaine est un "\" on le supprime
            If Me.TXT_SAVEPATH.Text.EndsWith("\") Then
                Me.TXT_SAVEPATH.Text.Trim("\")
            End If
            'Crée le dossier de sauvegarde avec un nom spécifié
            'Supprime les / et : de la date et de l'heure
            Dim DossierSave As String = Me.TXT_SAVEPATH.Text & "\Sauvegarde du " & Date.Now.ToShortDateString.Replace("/", "-") & " a " & Date.Now.ToShortTimeString.Replace(":", "-")
            If Not Directory.Exists(DossierSave) Then 's'il exciste : 2saves dans la même minute, on ne la fait pas
                Directory.CreateDirectory(DossierSave)
                'Pour chaque path demandé, copie son dossier
                For Each PathASave As String In Me.LB_PATHSASAVE.Items
                    If Directory.Exists(PathASave) Then
                        CopieDossier(New DirectoryInfo(PathASave), New DirectoryInfo(DossierSave & "\" & Path.GetFileName(PathASave)))
                    End If
                Next
            End If
        Else
            MsgBox("Sauvegarde échouée : le path de sauvegarde est invalide, veuillez le redéfinir")
        End If

    End Sub

    Sub NettoieNbSaves()

        Dim Compteur As Integer = 1
        For Each Repertoire As String In Directory.GetDirectories(Me.TXT_SAVEPATH.Text)
            'Si le repertoire est un répertoire de sauvegarde
            If Path.GetFileName(Repertoire).Contains("Sauvegarde") Then
                'Incrementation du compteur
                Compteur += 1
            End If
        Next

        If Compteur > Me.NUM_NBSAVE.Value Then
            'Détermination du plus ancien
            Dim PlusAncien As DirectoryInfo
            Dim DatePlusAncienne As Date = Date.Now
            For Each Repertoire As String In Directory.GetDirectories(Me.TXT_SAVEPATH.Text)
                'Si le repertoire est un répertoire de sauvegarde
                If Path.GetFileName(Repertoire).Contains("Sauvegarde") Then
                    'Si le répertoire est plus ancien de que le précédent
                    If (Directory.GetCreationTime(Repertoire) < DatePlusAncienne) Then
                        'On le place en plus ancien
                        DatePlusAncienne = Directory.GetCreationTime(Repertoire)
                        PlusAncien = New DirectoryInfo(Repertoire)
                    End If
                End If
            Next

            'Supprime le plus vieux
            If PlusAncien.Exists Then
                PlusAncien.Delete(True)
            End If
        End If

    End Sub

    Sub CopieDossier(ByVal DossierSource As DirectoryInfo, ByVal DossierDesination As DirectoryInfo)

        'Crée le dossier
        DossierDesination.Create()

        'Copie les fichiers
        For Each Fichier As FileInfo In DossierSource.GetFiles()
            Fichier.CopyTo(Path.Combine(DossierDesination.FullName, Fichier.Name))
        Next

        'Recommence pour les sous-repertoires
        For Each SousRepertoire As DirectoryInfo In DossierSource.GetDirectories()
            CopieDossier(SousRepertoire, DossierDesination.CreateSubdirectory(SousRepertoire.Name))
        Next

    End Sub

#End Region

End Class


Eh bien, ça devient conséquent.

Comme vous pouvez le voir dès la première ligne, j'ai essayé de rendre le programme "flexible". Autrement dit, il me suffit de changer les constantes pour changer le nom du fichier ini par exemple, c'est cette constante qui est utilisée à chaque fois qu'une fonction demande le nom de ce fichier.

Trois grandes sections se distinguent :
  • L'interface, contenant la réaction aux boutons, etc ...
  • Le fichier ini, contenant tout ce qui touche à la configuration.
  • Finalement la sauvegarde.


Une rapide vue d'ensemble du fonctionnement :
  • Récupération de la configuration
    • Si elle n'existe pas création du fichier ini
    • Si elle est corrompue, recréation du fichier ini
  • A chaque tick de timer (timer configuré sur le temps souhaité entre 2 sauvegardes), on effectue la sauvegarde
  • Avec le bouton sauvegarde manuelle la même action est réalisée
  • Le sauvegarde consiste a créer un dossier sous la forme "Sauvegarde du DD-MM-AAAA a HH-MM"
  • Puis copie l'intégralité des dossiers en respectant leur arborescence.


L'interface



Voilà donc, commençons par analyse le plus simple : l'interface.

Première information : l'ouverture de la folderbrowserdialog lors du clic sur la textbox.
Eh bien, rien de sorcier, l'évènement clic de la textbox !

Code : VB.NET
1
2
3
4
5
6
7
8
Private Sub TXT_SAVEPATH_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TXT_SAVEPATH.Click

        'Ajoute la ligne seulement si un dossier a été selectioné dans le dialogue
        If Me.BD_DOSSIER.ShowDialog() Then
            Me.TXT_SAVEPATH.Text = Me.BD_DOSSIER.SelectedPath
        End If

    End Sub


Eh bien lors du clic on se sert du contrôle "BD_DOSSIER" qui est mon FolserBrowserDialog. Vu que c'est une boite de dialogue, c'est la fonction ShowDialog qui est appellée. Puis on récupère la sélection avec le propriété SelectedPath.

Le bouton d'ajout à le même principe mais il agit sur la listbox, sur le système que le treeview que nous avons étudiés auparavant, il faut créer, non plus des nodes, mais des items.

Code : VB.NET
1
Me.LB_PATHSASAVE.Items.Add(Me.BD_DOSSIER.SelectedPath)


C'est dans le membre "Items" que les fonctions spécifiques a ces objets sont trouvables. La méthode Add() permet d'ajouter un item, avec comme valeur le dossier sélectionné.

Pour la suppression :

Code : VB.NET
1
2
3
4
5
6
'Vérifie si une ligne est sélectionnée dans la listbox
        If Not Me.LB_PATHSASAVE.SelectedItem Is Nothing Then
            Me.LB_PATHSASAVE.Items.Remove(Me.LB_PATHSASAVE.SelectedItem)
        Else
            MsgBox("Selectionnez un path à supprimer")
        End If


Vous vous apercevez qu'une vérification est faite pour voir si une ligne est sélectionnée avec If Not Me.LB_PATHSASAVE.SelectedItem Is Nothing Then . Vous vous apercevez que je n'utilise pas le symbole "<>" pour dire différent mais "not ... is nothing" c'est une autre notation plus littérale, tout dépend des goûts de chacun.
Ensuite on supprime avec Items.Remove en passant comme paramètre la ligne selectionnée.

Pour les autres boutons, la sauvegarde des paramètres appelle la méthode SauvegardeFichierIni() que nous allons étudier. Le timer et la sauvegarde manuelle appellent la méthode Sauvegarde() que nous allons aussi étudier.

Sauvegarde en fichier .ini



Attaquons tout de suite la sauvegarde.

Pour ce qui est de cette sauvegarde, je vérifie la présence d'un dossier dans la textbox et si ce dossier est valide. Ensuite j'appelle la fonction File.WriteAllLines(FichierIni, CreeStructureFichierIni(Me.TXT_SAVEPATH.Text, Me.NUM_SAVETIME.Value, Me.NUM_NBSAVE.Value, Me.LB_PATHSASAVE.Items)) qui s'occupe de créer un fichier et d'entrer dedans un tableau de string (une case de tableau pour une ligne).
En premier paramètre, le fichier de destination, c'est notre constante avec le nom du fichier ini. Le second, autrement dit le tableau de string, c'est une fonction que nous allons étudier tout de suite :

Code : VB.NET
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
Function CreeStructureFichierIni(ByVal SavePath As String, ByVal TempsSave As Integer, ByVal Nbsaves As Integer, ByVal PathsASave As ListBox.ObjectCollection) As String()

        'Crée un tableau du nombre de lignes requises
        Dim FichierIni(LignesFichierIni + PathsASave.Count) As String
        'Replit la structure du fichier ini
        FichierIni(0) = ";Fichier de configuration du Zbackup"
        FichierIni(1) = "[configuration]"
        FichierIni(2) = CleSavePath & "=" & SavePath
        FichierIni(3) = CleTempSave & "=" & TempsSave
        FichierIni(4) = CleNbSaves & "=" & Nbsaves
        FichierIni(5) = ""
        FichierIni(6) = "[paths]"
        'Rempli dynamiquement les paths souhaités
        Dim Compteur As Integer = LignesFichierIni
        For Each Path As String In PathsASave
            Compteur += 1
            FichierIni(Compteur) = ClePaths & Compteur - LignesFichierIni & "=" & Path
        Next

        Return FichierIni

    End Function



Les valeurs passées en paramètres auraient pu être remplacées par des récupérations directement à l'intérieur de la fonction. Bref. Un tableau est crée avec comme taille le nombre de lignes initiales plus le nombre de paths à insérer.
Pour les premières lignes, j'écris manuellement dedans les premières clés. Ce qui nous donne dans le fichier ini une fois crée :

Code : Autre
1
2
3
4
5
6
7
8
;Fichier de configuration du Zbackup
[configuration]
SavePath=C:\Save
TempSave=1
NbSaves=3

[paths]
Paths1=C:\ASave


Deux sections donc : une configuration, une autre paths.
La section configuration contient le répertoire où sauvegarder, le temps entre 2 saves et le nombre de saves max.
La section paths contient les différents paths, tous avec un numéro différent. Les techniques peuvent différer, il aurait été possible de mettre tous les paths sur la même ligne, séparés par des ";".

Bref. La création du fichier n'est pas sorcier, le tableau de variables "FichierIni()" est renvoyée et est écrite dans le fichier.

Maintenant que vous avez vus comment le remplir, voyons comment récupérer les valeurs.

Donc pour cela une petite fonction à laquelle on passe en paramètre la clé à récupérer.

Code : VB.NET
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Function RecupereCleFichierIni(ByVal Cle As String) As String

        For Each Ligne As String In File.ReadAllLines(FichierIni)
            'Découpe la ligne au niveau de "=" (s'il existe), 
            'compare la premiere partie de la ligne (soit la clé)
            If Ligne.Split("=")(0) = Cle Then
                'Recupère la seconde partie de la ligne (soit la valeur)
                Return Ligne.Split("=")(1)
            End If
        Next
        'Sinon ne retourne rien
        Return ""

    End Function


Principe de cette fonction : on parcours toutes les lignes du ini, à chaque ligne on la découpe grâce à la fonction Split().
La fonction split s'applique sur une chaine de caractères, elle permet de "découper" cette chaine à chaque occurrence du caractère ou de la chaine passée en argument. Donc exemple :
Pour une chaine de caractère sous la forme "Cle1=Valeur1" un Split("=") donnera un tableau de string sous la forme.
Tableau(0) = Cle1
Tableau(1) = Valeur1

Donc un bête et méchant test sur le tableau(0) qui est retourné avec la clé souhaitée nous indique la ligne contenant la clé voulue. Une fois cette ligne atteinte, le tableau(1), celui contenant la valeur est retourné.
Si la clé n'est pas trouvée, on retourne "".

Il fallait y penser.

Sauvegarde



Attaquons tout de suite le principe de la sauvegarde.

La méthode Sauvegarde() effectue diverses vérification sur la présence des dossiers, elle crée le dossier dans lequel la sauvegarde va être placée et lance la méthode CopieDossier() que voici :

Code : VB.NET
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
Sub CopieDossier(ByVal DossierSource As DirectoryInfo, ByVal DossierDesination As DirectoryInfo)

        'Crée le dossier
        DossierDesination.Create()

        'Copie les fichiers
        For Each Fichier As FileInfo In DossierSource.GetFiles()
            Fichier.CopyTo(Path.Combine(DossierDesination.FullName, Fichier.Name))
        Next

        'Recommence pour les sous-repertoires
        For Each SousRepertoire As DirectoryInfo In DossierSource.GetDirectories()
            CopieDossier(SousRepertoire, DossierDesination.CreateSubdirectory(SousRepertoire.Name))
        Next

    End Sub


Cette méthode prend comme arguments des variables de type DirectoryInfo. Ce n'est pas des variables communes : ce sont des objets. Il faut donc les instancier avec un new.

Lors de l'appel de la ligne avec CopieDossier(New DirectoryInfo(PathASave), New DirectoryInfo(DossierSave & "\" & Path.GetFileName(PathASave))) , j'instance deux objets avec comme paramètre les chemins des dossiers voulus.

Une fois dans la méthode de copie, un dossier est tout d'abord crée, les fichiers contenus y sont copiés également puis cette action est répétée pour tous ses sous répertoires. De la même manière que le treeview du chapitre précédent.

Il y a finalement la méthode de nettoyage des sauvegardes (si on demande qu'un certain nombre de sauvegardes). Elle parcourt les répertoires crées, récupère la date de création de chacun, identifie le plus vieux et le supprime en utilisant la récursivité de la méthode Directory.Delete.

Eh bien voilà. Le code décortiqué.

Allons un peu plus loin.

Récapitulatif fichier ini

Bien, procédons à un récapitulatif des fonctions que vous allez pouvoir utiliser dans vos futurs programmes pour créer et gérer un fichier .ini, je ne pense pas revenir dessus par la suite, autant tout résumer tout de suite.

La création



Tout d'abord pour la création du fichier ini.

Deux manières de procéder : la création manuelle en utilisant une fonction du genre :

Code : VB.NET
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Function CreeStructureFichierIni(ByVal SavePath As String, ByVal TempsSave As Integer, ByVal Nbsaves As Integer, ByVal PathsASave As ListBox.ObjectCollection) As String()

        'Crée un tableau du nombre de lignes requises
        Dim FichierIni(LignesFichierIni + PathsASave.Count) As String
        'Replit la structure du fichier ini
        FichierIni(0) = ";Fichier de configuration du Zbackup"
        FichierIni(1) = "[configuration]"
        FichierIni(2) = CleSavePath & "=" & SavePath
        FichierIni(3) = CleTempSave & "=" & TempsSave
        FichierIni(4) = CleNbSaves & "=" & Nbsaves
        FichierIni(5) = ""
        Return FichierIni

    End Function


Cette fonction est appelée manuelle car vous voyez que chaque ligne doit être écrite côté programmatique.
Très pratique et très visuel pour le programmeur, mais beaucoup moins agréable lorsque vous avez 100 clés de configuration à entrer.

Une autre méthode consiste a passer un tableau à deux dimensions de string, deux colonnes et autant de lignes que de clés.
La première colonne contenant les clés, la seconde les valeurs.

un rapide algorithme vous construit le même tableau de lignes que vous écrirez dans votre fichier avec WriteAllLines().

Code : VB.NET
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Function CreeStructureFichierIni(ByVal ClesValeurs(, ) As String) As String()
		
	Dim Ligne(10) As String
	'Par exemple ClesValeurs a deux dimensions sous la forme : (1, 10)
        'On divise la taille par 2 car elle correspond à l'ensemble des cellules et on a deux colonnes donc cellules / 2 = nbligne
	For i As Integer = 0 To te.Length / 2 
            Ligne(i) = ClesValeurs(0,i) & "=" & ClesValeurs(1,i)
        Next

    End Function


Mais ce genre d’algorithme est à faire par vos soins, il n'est pas très compliqué mais demande un léger travail de recherche.

La récupération de valeurs



Passons tout de suite à la récupération des valeurs.

Ma fonction faite dans ce TP devrait amplement suffir :

Code : VB.NET
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Function RecupereCleFichierIni(ByVal Cle As String) As String

        For Each Ligne As String In File.ReadAllLines(FichierIni)
            'Découpe la ligne au niveau de "=" (s'il existe), 
            'compare la premiere partie de la ligne (soit la clé)
            If Ligne.Split("=")(0) = Cle Then
                'Recupère la seconde partie de la ligne (soit la valeur)
                Return Ligne.Split("=")(1)
            End If
        Next
        'Sinon ne retourne rien
        Return ""

    End Function


On passe la clé souhaitée en argument, on récupère sa valeur.

Eh bien je pense que vous avez les éléments en main pour créer les fichier ini de tous nos prochains TP :diable: .

Pour aller plus loin

Bon, je ne vais pas continuer l'évolution car il me suffit amplement ainsi.

Cette petite idée de TP m'étant venu lors d'un aprem de programmation, j'ai l'habitude de sauvegarder régulièrement mon travail mais après une fausse manip tout mon projet s'est retrouvé converti et irrécupérable, impossible de faire machine arrière.

Ce petit programme effectuant des sauvegardes périodiques du travail m'aurait pu éviter cette erreur.

Bien, passons aux améliorations possibles.

Tout d'abord une sauvegarde plus propre et moins lourde.

Comment faire ?


Eh bien je suppose que vous avez déjà entendus parler de la compression zip. Elle convertit des dossiers et des fichiers en un seul fichier zip. On dit alors que nos fichiers sont compressés sous zip.
La même méthode utilise avec l'archivage et les rar.

Je ne vais pas vous aider plus sur cette voie car elle est réservée à ceux qui souhaitent effectuer un peu de recherche. Je vais juste vous donner quelques voies.

La première étant l'utilisation du namespace Compression contenu dans IO. Assez difficile à utiliser à mon avis, très fastidieux à mettre en place.

La seconde étant l'utilisation de l'utilitaire 7zip, utilitaire open source donc gratuit.
Voici sa fiche clubic : 7zip

Cet utilitaire dispose d'une interface graphique mais aussi d'une utilisation en ligne de commande.

Les commandes (arguments) possibles avec l’exécutable 7z.exe sont :

Image utilisateur


Cette manipulation est réservée aux plus expérimentés d'entre vous, il va falloir combiner commande et path de fichiers dans une fonction VB nommée : Shell() permettant l'éxécution shell de programmes.

Exemple : si votre 7z.exe est dans le dossier de votre programme, il faudra utiliser Shell("7z.exe a MonArchive.zip MonFichierAZipper").

Je vous laisse explorer cette voie qui semble prometteuse.


Reste ensuite comme améliorations possible un écran supplémentaire listant les sauvegardes effectuées, la possibilité de restaurer l'une d'entre elle.

Egalement une exécution de ce programme en arrière plan voire en tant que service.

Pour l'arrière plan il faudra déjà s'employer à rendre la forme principal à Visible = false.
Puis créer une icône contextuelle, un contrôle tout fait existe, cherchez dans votre boîte à outils.
Puis récupérer l'évènement clic ou doubleclic sur cette icone pour faire repasser votre forme à visible = true.

Finalement le lancement au démarrage : il faut créer un raccourci de votre programme ou placer votre programme dans le dossier :
C:\Users\@VOTREUSER@\AppData\Roaming\Microsoft\Windows\Start Menu\Programs

Que d'amélioration possible, en y passant un peu de temps votre programme peut devenir une véritable sauvegarde périodique de vos données vitales en restant discret et rapide. Et puis lors de notre partie concernant le réseau, une sauvegarde sur un FTP ou un serveur sera envisageable.

Voilà amis zéros, bonne chance !
Chapitre précédent Sommaire Chapitre suivant

Partager

7 commentaires pour "TP : ZBackup"
Note moyenne : 3.60 / 4 (543 votes)
Pseudo Commentaire
Hors ligne nonowh # Posté le 22/12/2010 à 21:40:08
Avatar

Avis : Mitigé Groupe : Bannis

j'ai pas encore lus mais je réserve la place :p

RIP Steve Jobs.
 
Hors ligne Hor@ce # Posté le 21/01/2011 à 19:01:23
Avatar

Avis : Décevant

Ça pique les yeux ! Quand on vois ça...

Code : VB.NET
1
2
3
4
5
6
7
8
Private Declare Function GetPrivateProfileString Lib "Kernel32" Alias "GetPrivateProfileStringA" _
    (ByVal lpApplicationName As String, _
    ByVal lpKeyName As String, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Short, _
    ByVal lpFileName As String) As Integer

    Private Declare Function WritePrivateProfileString Lib "Kernel32" Alias "WritePrivateProfileStringA" _
    (ByVal lpApplicationName As String, _
    ByVal lpKeyName As String, ByVal lpString As String, ByVal lplFileName As String) As Long


Beaucoup plus simple pour écrire et lire dans un fichier .ini...

Le plus dur ce n'est pas la programmation,
mais bien d'installer les différents logiciels requis.
 
Hors ligne griviere42 # Posté le 19/06/2011 à 16:46:09
Avatar

Citation : Hankerspace
sur le système que le treeview que nous avons étudiés auparavant


Tu as du oublier le mot "même" ;)

Windows publie tte une suite de logiciel gratuits!
Citation
Il y a 3 grands mensonges en informatique :
ça marche, c'est compatible et ça sort bientôt
 
Hors ligne electroinfo # Posté le 03/07/2011 à 13:25:23

Salut les zéros,

Je ne comprends pas, où intervalle du timer est remise à jour ?

En effet lors du lancement de la fenêtre, d'abbord on met une valeur dans intervalle du timer puis seulement ensuite on lit le fichier de configuration. Donc la valeur de intervalle du timer contenue dans le fichier de configuration n'est jamais mise dans la propriété intervalle du timer???
Hors ligne philos1980 # Posté le 16/03/2012 à 14:24:50

J'ai un avertissement à la ligne 230 du code.
if PlusAncien.Exists Then
L'exception NullReferenceException n'a pas été gérée
La référence d'objet n'est pas définie à une instance d'un objet.

Voir tous les commentaires