Sauvegarde des données d'un réseau en vbscript

Description

Descriptif du programme:
Cré une copie de sauvegarde de données se trouvant sur differents serveurs ou postes du réseau.
Le listing des sauvegarde à effectuer est inscrit dans un fichier texte. Le chemin de celui-ci devra être transmis au programme en tant qu'argument.
suppression de l'ancienne sauvegarde si le parametre "/raz" est transmis au programme.
Les fichiers systemes cachés ainsi que tous les chemins listés dans ExceptFile.txt et ExeptRep.txt ne seront pas sauvegardés.
Détection et gestion des chemins longs (chemins de plus de 256 caractères).
Tronque le nom des fichiers et dossiers à [MaxNameLength] caractères s'ils le dépassent.
Création de deux rapports:
un fichier rapport.txt qui contient la date de la sauvegarde, le listing des dossiers sauvegardés ainsi qu'un indicateur de déroulement de la sauvegarde (OK ou PB)
un fichier erreurs.txt qui contient toutes les erreurs et tous les avertissements
Création d'un fichier InfoSav.vbs dans le dossier 'démarrage' du pc indiquant l'état de la sauvegarde(en cours, OK ou PB).
Il s'exécute automatiquement à la fin de la sauvegarde si une session est déja ouverte ou à la prochaine ouverture de session.

Source / Exemple :


'*******************************************************************************
'***                      PROGRAMME DE SAUVEGARDE RESEAU
'*** descriptif:
'***    Cré une copie de sauvegarde de données se trouvant sur differents serveurs ou postes du réseau.
'***        Le listing des sauvegarde à effectuer est inscrit dans un fichier texte. Le chemin de celui-ci devra être transmis au programme en tant qu'argument.
'***    suppression de l'ancienne sauvegarde si le parametre "/raz" est transmis au programme
'***    Les fichiers systemes cachés ainsi que tous les chemins listés dans ExceptFile.txt et ExeptRep.txt ne seront pas sauvegardés
'***    Détection et gestions des chemins longs (chemins de plus de 256 caractères)
'***    Tronque à [MaxNameLength] caractères le nom des fichiers et dossiers dépassant [MaxNameLength] caractères
'***    Création de deux rapports:
'***        un fichier rapport.txt qui contient la date de la sauvegarde, le listing des dossiers sauvegardés ainsi qu'un indicateur de déroulement de la sauvegarde (OK ou PB)
'***        un fichier erreurs.txt qui contient toutes les erreurs et tous les avertissements
'***    Création d'un fichier InfoSav.vbs dans le dossier 'démarrage' du pc indiquant l'état de la sauvegarde(en cours, OK ou PB).
'***        Il s'exécute automatiquement à la fin de la sauvegarde si une session est déja ouverte ou à la prochaine ouverture de session.
'***
'*** utilisation:
'***    Définir tout d'abord les constantes spécifique à votre réseau cf ci-dessous
'***    Utilisez des fichiers batch pour lancer des sauvegardes (ci joint 2 ex: week.bat et weekend.bat)
'***    Utiliser le planificateur de tache windows pour planifier les sauvegardes
'***    NB: Tous les partages listés dans le fichier listing(week.txt weekend.txt etc...) doivent être accessibles. Vérifiez le en le parcourant avec l'explorateur window.
'***       Utiliser de préférence les partages d'administration windows de chaque lecteur (c$, d$, e$ etc...)
'***
'*** A venir:
'***    1)sauvegarde des ACL
'***    2)interface web d'administration des sauvegardes avec:
'***      configuration des variables du programme (MaxNameLength, racinesav, etc...)
'***      création et configuration des taches planifiées pour la sauvegarde
'***    3)Programme de restauration des données et des ACL
'***
'*******************************************************************************
On error resume next

' définition des constantes
' constantes à modifier par l'administrateur suivant la config désirée
const MaxNameLength = 60   'correspond à la longueur max des noms des dossiers et fichiers sauvegardés -> si la longueur dépasse, la sauvegarde se fera avec le noms tronqué à [MaxNameLength] caractère.
const racinesav = "e:\sauvegarde" 'correspond au dossier racine où sera stoqué la sauvegarde(disque dur externe usb ou ide/sata amovible)
                                  'NB: racinesav doit être un chemin du type lecteur:\dossier (ex e:\sav) et non un chemin du type lecteur:\ (ex E:\ ne fonctionnera pas)
const ScriptFilePath = "c:\documents and settings\all users\menu démarrer\programmes\démarrage\infosav.vbs" 'correspond au chemin du script qui aura pour tache d'afficher l'état de la sauvegarde (en cours, PB, OK)
const DriveTemp="x:"       'DriveTemp correspond au lecteur réseau qui sera utilisé pour la gestion des chemins long. NB: spécifier un lecteur libre

'constantes ne devant pas être modifiées
const MaxPathLength = 246  'correspond à la longueur max d'un chemin (+13 caracteres pour chemin\fichier) -> au dela, utilisation d'un lecteur réseau
const ForReading = 1
const ForWriting = 2
const ForAppending = 8
Const OverWrite = True

if len(trim(racinesav))<4 then msgbox "La constante 'racinesav' doit être un chemin du type lecteur:\dossier. Arrêt du programme.",vbCritical + vbOkOnly + vbSystemModal + 0,"Erreur sauvegarde.vbs" : wscript.quit

' déclaration de variables
dim listedossiers()   'tableau listant tous les sous-dossiers du dossier à sauvegarder
dim ListeExceptFile() 'tableau listant tous les fichiers à ne pas sauvegarder
dim ListeExceptRep()  'tableau listant tous les dossiers à ne pas sauvegarder
strcomputer = "."
erreurglobale=false
FindLongPath=false
Set objFSO = CreateObject("Scripting.FileSystemObject")

' Récupération et traitement des arguments
if WScript.Arguments.item(0)<>"/?" then ScriptWrite("initialisation") 'cré le script InfoSav.vbs
err.clear()
if not objFSO.FolderExists(racinesav) Then objFSO.CreateFolder(racinesav) 'doit impérativement exister pour l'écriture d'erreurs
if err.number<>0 then exitprog()

Set objArgs = WScript.Arguments
if WScript.Arguments.Count<1 then ' erreur: il faut au moins 1 argument
        Set objErrFile = objFSO.OpenTextFile(racinesav & "\erreurs.txt", ForWriting, True)
        ErrWrite("initialisation")
        ErrWrite("Le script a été lancé sans aucun argument. Taper 'sauvegarde.vbs /?' pour plus d'informations.")
        exitprog()
end if
if WScript.Arguments.item(0)="/?" then 'affiche aide
        wscript.echo "AIDE POUR LE LANCEMENT DU SCRIPT DE SAUVEGARDE:" & chr(13) & chr(13) & "   sauvegarde.vbs /raz [workfile]" & chr(13) & "      /raz :          supprime entièrement l'ancienne sauvegarde. (facultatif)" & chr(13) & "      workfile :   le chemin du fichier contenant la liste des dossiers à sauvegarder."
        exitprog()
end if
i=0
if WScript.Arguments.item(0)="/raz" then
        'suppression de toute l'ancienne sauvegarde
        if not deltree(racinesav) then                 'racinesav n'a pas pu être supprimé
                Set objErrFile = objFSO.OpenTextFile(racinesav & "\erreurs.txt", ForWriting, True)
                ErrWrite("initialisation")
                ErrWrite("L'ancienne sauvegarde (" & racinesav & ") n'a pas pu être supprimée")
                if WScript.Arguments.Count=1 then
                        ErrWrite("Aucun listing de travail n'a été transmis au programme")
                        exitprog()
                end if
        else                                    'racinesav a été supprimé
                err.clear()
                objFSO.CreateFolder(racinesav)
                if err.number<>0 then exitprog()
                if WScript.Arguments.Count=1 then
                        Set objErrFile = objFSO.OpenTextFile(racinesav & "\erreurs.txt", ForWriting, True)
                        ErrWrite("initialisation")
                        ErrWrite("L'ancienne sauvegarde a été supprimée mais aucun listing de travail n'a été transmis au programme")
                        exitprog()
                else
                        Set objErrFile = objFSO.OpenTextFile(racinesav & "\erreurs.txt", ForWriting, True)
                        ErrWrite("initialisation")
                end if
        end if
        i=1
else
        Set objErrFile = objFSO.OpenTextFile(racinesav & "\erreurs.txt", ForAppending, True)
        ErrWrite("initialisation")
end if

If not objFSO.FileExists(WScript.Arguments.item(i)) Then
        ErrWrite("Le fichier passé en paramètre contenant le listing du travail a exécuter n'existe pas")
        exitprog()
end if
Err.Clear()
Set objWorkFile = objFSO.OpenTextFile(WScript.Arguments.item(i), ForReading, false)
If Err.Number <> 0 Then
        ErrWrite("Erreur d'ouverture du fichier passé en paramètre")
        exitprog()
end if

' Création du fichier contenant le script affichant les infos sur le déroulement de la sauvegarde
ScriptWrite("debut")

' ouverture du fichier rapport.txt contenant les infos sur le déroulement de la sauvegarde
Err.Clear()
Set objTextFile = objFSO.OpenTextFile(racinesav & "\rapport.txt", ForAppending, True)
objTextFile.WriteLine("   ")
objTextFile.WriteLine("SAUVEGARDE DU " & date)
If Err.Number <> 0 Then ErrWrite("Erreur d'ouverture ou d'écriture du fichier ./rapport.txt")

'initialisation des tableaux ListeExceptionFile() et ListeExceptRep()
NbreExceptFile=0
exception "readfile", "file" 'lecture du fichier ./ExceptFile.txt
NbreExceptRep=0
exception "readfile", "rep"  'lecture du fichier ./ExceptRep.txt

'Lancement des sauvegardes
Do While Not objWorkFile.AtEndOfStream 'lecture du fichier contenant les chemins à sauvegarder
        'suppression des espaces à droite et à gauche et suppression du \ en fin de chemin s'il existe
        source=trim(objWorkFile.ReadLine)
        if mid(source, len(source), 1)="\" then source = mid(source, 1, len(source)-1)
        'traitement
        if not objFSO.FolderExists(source) then
                if lcase(mid(source,1,3))<>"rem" and source<>"" then
                        ErrWrite("Le dossier '" & source & "' n'existe pas ou n'a pas été trouvé")
                        decalage=""
                        while len(source)+len(decalage)<50
                                decalage=decalage & " "
                        wend
                        objTextFile.WriteLine("  Le " & date & " de " & time & " à " & time & ": sauvegarde de: " & source & decalage &  "Contrôle: ERREUR   ")
                        erreurglobale=true
                end if
        else
                if mid(source, 1, 2)<>"\\" then         'chemin local
                        'transforme le chemin local en chemin réseau et remplace le : du lecteur par $ (utilisation du partage d'administration windows: C$, D$, E$ etc...)
                        Set oNetwork = CreateObject("WScript.Network")
                        source = "\\" & oNetwork.ComputerName & "\" & mid(source, 1, 1) & "$" & mid(source, 3, len(source))
                        Set oNetwork = nothing
                end if
                cible = racinesav & mid(source, 2, len(source))
                call sauve()
        end if
loop

' Création du fichier contenant le script affichant les infos sur le déroulement de la sauvegarde
ScriptWrite("fin")
exitprog()

'------------------------------------------------------------
' Procédure de sauvegarde et de contrôle
sub sauve()
dim CopyAfterAll()
On error resume next
        DateDepart=date
        errsauve=false
        depart=time
        'suppression du dossier cible s'il existe
        if objFSO.FolderExists(cible) and len(cible)>3 Then
                if not deltree(cible) then ErrWrite("Le dossier " & cible & " n'a pas pu être supprimé")
        end if

        'création de l'arborescence cible
        if len(cible) > 3 then 'du genre c:\undossier\unautre\etc
                i = 4
                do
                        slach = Instr(i, cible, "\")
                        if slach > 4 then    ' un \ a été trouvé
                                dossier = mid(cible, 1, slach-1)
                                If not objFSO.FolderExists(dossier) Then
                                        objFSO.CreateFolder(dossier)
                                end if
                        else
                                if len(cible) <= i-1 then exit do
                                If not objFSO.FolderExists(cible) Then
                                        objFSO.CreateFolder(cible)
                                end if
                        end if
                        i = slach + 1
                loop until slach < 5
        end if

        'Initialise le tableau listedossier(): contient tous les sous dossiers de "source"
        NbreDossier=listerep(source)

        'sauvegarde de tous les fichiers sauf les fichiers systemes cachés
        if NbreDossier>0 then
                'Modification du tableau listedossiers(): troncature de tous les noms > MaxNameLenght
                SearchAndRenLongName(NbreDossier)

                'Création de la structure de répertoire
                debut=len(source)+1
                for i=2 to NbreDossier 'le dossier cible de base est déja créé (i=1)
                        Err.Clear()
                        if listedossiers(1,i)="" then dossier=cible & mid(listedossiers(0,i), debut) else dossier=cible & mid(listedossiers(1,i), debut)
                        if len(dossier)<=MaxPathLength then 'on ne cré que les dossiers < MaxPathLength. Toutes les données se trouvant dans les sous dossiers seront copiés dans ce dossier.
                                objFSO.CreateFolder(dossier)
                                If Err.Number <> 0 Then
                                        ErrWrite("Pb création structure répertoire: le dossier '" & dossier & "' n'a pas pu être créé.")
                                        erreurglobale=true
                                        errsauve=true
                                end if
                        end if
                next

                'recopie de tous les fichiers de tous les dossiers sauf les fichiers systemes cachés
                for i=1 to NbreDossier
                        if listedossiers(1,i)="" then index=0 else index=1
                        dossier=listedossiers(0,i)
                        if len(dossier)>MaxPathLength then dossier=smallpath(dossier, DriveTemp, MaxPathLength)
                        Set objFolder = objFSO.GetFolder(dossier)
                        Set colFiles = objFolder.Files
                        if len(listedossiers(0,i))<=MaxPathLength and not TestAccessFile(colFiles) then
                                dossier=smallpath(dossier, DriveTemp, MaxPathLength)
                                Set objFolder = objFSO.GetFolder(dossier)
                                Set colFiles = objFolder.Files
                        end if
                        NbreCopyAfterAll=0
                        redim CopyAfterAll(1,0)
                        For Each objFile in colFiles
                                if not exception(listedossiers(0,i) & "\" & objFile.name, "file") and (objFile.Attributes AND 6)<>6 then
                                        dossier=cible & mid(listedossiers(index,i), debut)
                                        if len(dossier)>MaxPathLength then
                                                FindLongPath=true
                                                ErrWrite("Le fichier '" & listedossiers(0,i) & "\" & objFile.name & "' doit être sauvegardé dans un dossier parent(Chemin trop long)")
                                        end if
                                        ret=CopyFile(objFile.Path, dossier, objFile.name)
                                        if ret<0 then
                                                if ret=-1 then   'objfile.name>MaxNameLenght
                                                        NbreCopyAfterAll=NbreCopyAfterAll+1
                                                        redim preserve CopyAfterAll(1,NbreCopyAfterAll)
                                                        CopyAfterAll(0,NbreCopyAfterAll)=objFile.Path
                                                        CopyAfterAll(1,NbreCopyAfterAll)=dossier
                                                end if
                                                if ret=-3 then 'erreur de copie du fichier
                                                        ErrWrite("Erreur de copie du fichier " & listedossiers(0,i) & "\" & objFile.name)
                                                        erreurglobale=true
                                                        errsauve=true
                                                end if
                                        else
                                                if objFile.size<>ret then
                                                        ErrWrite("Erreur sur le fichier '" & listedossiers(0,i) & "\" & objFile.name & "'. La taille du fichier source(" & objFile.size & ") est différente de celle du fichier cible(" & ret & ").")
                                                        erreurglobale=true
                                                        errsauve=true
                                                end if
                                        end if
                                end if
                        Next
                        for j=1 to NbreCopyAfterAll 'sauvegarde de tous les fichiers devant être renommés
                                ret=CopyFile(CopyAfterAll(0,j), CopyAfterAll(1,j), "*")
                                if ret=-3 then 'erreur de copie du fichier
                                        ErrWrite("Erreur de copie du fichier " & CopyAfterAll(0,j))
                                        erreurglobale=true
                                        errsauve=true
                                else
                                        Set objFile = objFSO.GetFile(CopyAfterAll(0,j))
                                        if objFile.size<>ret then
                                                ErrWrite("Erreur sur le fichier '" & CopyAfterAll(0,j) & "'. La taille du fichier source(" & objFile.size & ") est différente de celle du fichier cible(" & ret & ").")
                                                erreurglobale=true
                                                errsauve=true
                                        end if
                                end if
                        next
                next
        end if

        fin=time
        decalage=""
        while len(source)+len(decalage)<50
                decalage=decalage & " "
        wend
        Err.Clear()
        if errsauve=true then
                objTextFile.WriteLine("  Le " & DateDepart & " de " & depart & " à " & fin & ": sauvegarde de: " & source & decalage & "Contrôle: ERREUR   ")
        else
                objTextFile.WriteLine("  Le " & DateDepart & " de " & depart & " à " & fin & ": sauvegarde de: " & source & decalage & "Contrôle: OK       ")
        end if
        If Err.Number <> 0 Then ErrWrite("Erreur d'écriture dans le fichier objtextfile")
end sub

'------------------------------------------------------------
' Fonction de copie de fichiers avec gestion des noms longs et dossiers longs
function CopyFile(Fichier_Source, Chemin_Cible, Nom_Cible)
On Error Resume Next
'CopyFile=size fichier cible    traitement OK
'CopyFile=-1                    NomCible>MaxNameLength
'CopyFile=-3                    Erreur de copy du fichier
 FichierSource=Fichier_Source
 CheminCible=Chemin_Cible
 NomCible=Nom_Cible

 if len(CheminCible)>MaxPathLength then 'FichierSource sera copié dans le premier sur dossier accessible et renommé si necessaire
        do  'recherche du dernier sur dossier <= MaxPathLength
                k=InstrRev(CheminCible, "\")
                CheminCible=mid(CheminCible, 1, k-1)
                if k<=MaxPathLength then exit do
        loop
        NomCible="*"
 end if

 MaxLongName=MaxPathLength +12 -len(CheminCible) 'longueur max d'un chemin MaxPathLength + 13 avec fichier (\nomfich.txt) -> sans l' "\" 12
 if MaxLongName>MaxNameLength then MaxLongName=MaxNameLength
 if len(NomCible)>MaxLongName then CopyFile=-1 : exit function 'le fichier doit être renommé -> sera traité une fois que les fichiers courts auront été sauvegardés
 if NomCible="*" then 'on détermine le nom et l'extension du fichier source puis on recherche un nom unique tout en gardant l'extension
        k=InstrRev(FichierSource, "\")
        NomCible=mid(FichierSource, k+1)
        k=InstrRev(NomCible, ".")
        extension=""
        if len(NomCible)-k <=4 and len(NomCible)-k > 0 then
                extension=mid(NomCible, k)
                NomCible=mid(NomCible, 1, k-1)
        end if

        id=0
        if len(NomCible)>MaxLongName-len(extension) then id=1 : NomCible=mid(NomCible, 1, MaxLongName-len(extension)-2) & "_0"
        do while objFSO.FileExists(CheminCible & "\" & NomCible & extension)
                str_id="_" & Cstr(id)
                nbrechar=len(NomCible)-len(str_id)
                if nbrechar<0 then CopyFile=-3 : exit function
                NomCible=mid(NomCible, 1, nbrechar) & str_id
                id=id+1
        loop
        NomCible=NomCible & extension
 end if

 Err.Clear()
 objFSO.CopyFile FichierSource, CheminCible & "\" & NomCible, OverWrite
 if Err.number<>0 then CopyFile=-3 : exit function
 Set objTemp = objFSO.GetFile(CheminCible & "\" & NomCible)
 objTemp.Attributes = 0
 CopyFile=objTemp.size
end function

'------------------------------------------------------------
' Fonction de listing des sous dossiers d'un dossier sauf dossiers systemes cachés
function listerep(dossier)
On error resume next
Set objFSO = CreateObject("Scripting.FileSystemObject")
redim listedossiers(1,1)
'listedossiers(0, x): path dossier source.
'listedossiers(1, x): contient path dossier cible(qui sera initialisé lors de la création de la structure de repertoire si le nom du dossier cible est différent de celui du dossier source)

If not objFSO.FolderExists(dossier) Then listerep=0 : exit function
listedossiers(0,1)=dossier
dimtab=1
ajout=2
Err.Clear()
i=1
fin = 1

'recherche de tous les sous dossiers
do
        do
                if (len(listedossiers(0,i)) > MaxPathLength) then 'avec mappage immédiat gestion chemin long
                        CheminCourt=smallpath(listedossiers(0,i), DriveTemp, MaxPathLength)
                        Err.Clear()
                        Set objFolder = objFSO.GetFolder(CheminCourt)
                        Set colSubfolders = objFolder.Subfolders
                        tempon=colSubfolders.count
                        If Err.Number <> 0 Then
                                ErrWrite("Erreur dans fonction listerep(). Problème d'accés au dossier '" & listedossiers(0,i) & "'.")
                                for j=i+1 to ajout-1
                                        listedossiers(0, j-1)=listedossiers(0, j)
                                next
                                fin=fin-1
                                ajout=ajout-1
                                i=i-1
                                listedossiers(0, ajout)=""
                        elseif colSubfolders.count > 0 then
                                dimtab = dimtab + colSubfolders.count
                                redim Preserve listedossiers(1,dimtab)
                                For Each objSubfolder in colSubfolders
                                        tempon=retrievepath(objSubfolder.path)
                                        If not exception(tempon, "rep") and (objSubFolder.Attributes AND 6)<>6 Then
                                                listedossiers(0,ajout) = tempon
                                                ajout = ajout + 1
                                        end if
                                Next
                        end if
                else  'sans mappage immédiat
                        Err.Clear()
                        Set objFolder = objFSO.GetFolder(listedossiers(0,i))
                        Set colSubfolders = objFolder.Subfolders
                        tempon=colSubfolders.count
                        If Err.Number <> 0 Then
                                ErrWrite("Erreur dans fonction listerep(). Problème d'accés au dossier '" & listedossiers(0,i) & "'.")
                                for j=i+1 to ajout-1
                                        listedossiers(0, j-1)=listedossiers(0, j)
                                next
                                fin=fin-1
                                ajout=ajout-1
                                i=i-1
                                listedossiers(0, ajout)=""
                        elseif colSubfolders.count > 0 then
                                dimtab = dimtab + colSubfolders.count
                                redim Preserve listedossiers(1,dimtab)
                                mappage=false
                                if TestAccessSubfolder(colsubfolders)=false then
                                        mappage=true
                                        CheminCourt=smallpath(listedossiers(0,i), DriveTemp, MaxPathLength)
                                        Set objFolder = objFSO.GetFolder(CheminCourt)
                                        Set colSubfolders = objFolder.Subfolders
                                end if

                                For Each objSubfolder in colSubfolders
                                        if mappage=true then tempon=retrievepath(objSubfolder.path) else tempon=objSubfolder.path
                                        If not exception(tempon, "rep") and (objSubFolder.Attributes AND 6)<>6 Then
                                                listedossiers(0,ajout)=tempon
                                                ajout = ajout + 1
                                        end if
                                Next
                        end if
                end if
                i=i+1
        loop while i<=fin
        if ajout-1 = fin then exit do 'aucun sous dossier n'a été trouvé
        i = fin+1
        fin = ajout-1
loop
listerep=fin
If Err.Number <> 0 Then ErrWrite("Une erreur s'est produite dans la fonction listerep().")
end function

'------------------------------------------------------------
' Procédure de création du script permettant d'informer l'administrateur du bon ou mauvais déroulement de la sauvegarde
sub ScriptWrite(etape)
On error resume next
Err.Clear()
Set objscriptFile = objFSO.OpenTextFile(ScriptFilePath, Forwriting, True)

if etape="initialisation" then
        objscriptFile.WriteLine("Set objFSO = CreateObject(" & chr(34) & "Scripting.FileSystemObject" & chr(34) & ")")
        objscriptFile.WriteLine("msgbox" & CHR(34) & "L'initialisation du programme n'a pas pu se faire." & CHR(34) & " & chr(13) & " & CHR(34) & "L'erreur se situe dans les arguments passés au script ou à la création du dossier racine de sauvegarde." & chr(34) & ",," & chr(34) & "Rapport sauvegarde" & chr(34))
        objscriptFile.WriteLine("objFSO.DeleteFile(" & chr(34) & ScriptFilePath & chr(34) & ")")
end if

if etape="debut" then
        objscriptFile.WriteLine("Set objFSO = CreateObject(" & chr(34) & "Scripting.FileSystemObject" & chr(34) & ")")
        objscriptFile.WriteLine("msgbox" & CHR(34) & "La sauvegarde est bloquée ou n'est pas terminée. A VERIFIER" & chr(34) & ",," & chr(34) & "Rapport sauvegarde" & chr(34))
        objscriptFile.WriteLine("objFSO.DeleteFile(" & chr(34) & ScriptFilePath & chr(34) & ")")
end if

if etape="fin" then
        ARLN=""
        if FindLongPath=true then ARLN= CHR(34) & " & vbCrLf & " & CHR(34) & "(Des chemins longs ont été trouvés)"
        if erreurglobale=true then
                objscriptFile.WriteLine("Set objFSO = CreateObject(" & chr(34) & "Scripting.FileSystemObject" & chr(34) & ")")
                objscriptFile.WriteLine("msgbox" & CHR(34) & "Des erreurs ont été détectées pendant la sauvegarde. Pour plus d'informations, éditer le fichier rapport.txt et erreurs.txt." & ARLN & chr(34) & ",," & chr(34) & "Rapport sauvegarde" & chr(34))
                objscriptFile.WriteLine("objFSO.DeleteFile(" & chr(34) & ScriptFilePath & chr(34) & ")")
        else
                objscriptFile.WriteLine("Set objFSO = CreateObject(" & chr(34) & "Scripting.FileSystemObject" & chr(34) & ")")
                objscriptFile.WriteLine("msgbox" & CHR(34) & "La sauvegarde s'est effectuée correctement." & ARLN & chr(34) & ",," & chr(34) & "Rapport sauvegarde" & chr(34))
                objscriptFile.WriteLine("objFSO.DeleteFile(" & chr(34) & ScriptFilePath & chr(34) & ")")
        end if
end if
objscriptFile.close
If Err.Number <> 0 Then ErrWrite("Erreur d'ouverture ou d'écriture du fichier objsriptfile")
end sub

'------------------------------------------------------------
' Procédure d'écriture des erreurs
sub ErrWrite(texte)
'On error resume next
        if texte="initialisation" then
                objErrFile.WriteLine("RAPPORT D'ERREURS PENDANT LA SAUVEGARDE DU " & date & ":")
        else
                if Err.Number<>0 then
                        objErrFile.WriteLine("   " & texte & "(erreur" & Err.Number & ": " & err.description & ")")
                else
                        objErrFile.WriteLine("   " & texte)
                end if
        end if
        Err.Clear()
end sub

'------------------------------------------------------------
' fonction permettant de lire le fichier ExceptFile.txt ou ExeceptRep.txt contenant les fichiers ou dossiers ne devant pas être copiés
' pourquoi: Certain fichier ne pouvant jamais être copiés(systeme en cours d'execution), on évite de les traiter pour ne pas occasionner d'erreur
function exception(TemponPath, RepOrFile)
On error resume next
        RepOrFile=lcase(RepOrFile)
        path=lcase(TemponPath)
        exception=false
        if path="readfile" then  'lecture du fichier; renvoi true si des exceptions ont été trouvées sinon false
                Err.Clear()
                if RepOrFile="rep" then Set objExceptFile = objFSO.OpenTextFile("ExceptRep.txt", ForReading, false)
                if RepOrFile="file" then Set objExceptFile = objFSO.OpenTextFile("ExceptFile.txt", ForReading, false)
                If Err.Number <> 0 Then
                        if RepOrFile="rep" then NbreExceptRep=0 else NbreExceptFile=0
                        exit function
                end if
                Do While Not objExceptFile.AtEndOfStream
                        tempon=trim(objExceptFile.ReadLine)
                        if tempon<>"" and lcase(mid(tempon, 1, 3))<>"rem" then
                                if RepOrFile="rep" then
                                        NbreExceptRep = NbreExceptRep + 1
                                        redim Preserve listeExceptRep(NbreExceptRep)
                                        ListeExceptRep(NbreExceptRep) = lcase(tempon)
                                else
                                        NbreExceptFile = NbreExceptFile + 1
                                        redim Preserve listeExceptFile(NbreExceptFile)
                                        ListeExceptFile(NbreExceptFile) = lcase(tempon)
                                end if
                        end if
                loop
                objExceptFile.close
                exit function
        end if

        if RepOrFile="file" and NbreExceptFile>0 then
                for y=1 to NbreExceptFile
                        if ListeExceptFile(y)=path then
                                exception=true
                                exit function
                        end if
                next
        end if
        if RepOrFile="rep" and NbreExceptRep>0 then
                for y=1 to NbreExceptRep
                        PosEtoile=instr(ListeExceptRep(y), "*")
                        if PosEtoile then
                                find=true
                                tempon1=ListeExceptRep(y)
                                tempon2=path
                                do  'vérifie si tempon1 et tempon2 sont identiques en écartant les sous-dossier marqués '*'
                                        if mid(tempon1, 1, PosEtoile-1)<>mid(tempon2, 1, PosEtoile-1) then  find=false : exit do
                                        tempon1=mid(tempon1, PosEtoile+2)
                                        tempon2=mid(tempon2, PosEtoile)
                                        tempon2=mid(tempon2, instr(tempon2,"\")+1)
                                        PosEtoile=instr(tempon1, "*")
                                loop  while PosEtoile>0
                                if find=true and instr(tempon2, tempon1) then exception=true : exit function
                        else
                                if ListeExceptRep(y)=path then
                                        exception=true
                                        exit function
                                end if
                        end if
                next
        end if
end function

'------------------------------------------------------------
' Procédure de fermeture du script
sub exitprog()
On error resume next
        tempon=smallpath("", DriveTemp, MaxPathLength) 'supprime le lecteur réseau s'il existe
        objtextFile.close
        objErrFile.close
        objWorkFile.close
	'Lance le script d'information sur le déroulement de la sauvegarde si une session est ouverte
        if objFSO.FileExists(ScriptFilePath) Then
                Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
                Set colComputer = objWMIService.ExecQuery("Select * from Win32_ComputerSystem")
                For Each objComputer in colComputer
                        if not isnull(objComputer.UserName) then
                                Set WshShell = WScript.CreateObject("WScript.Shell")
                                WshShell.Run (chr(34) & ScriptFilePath & chr(34))
                        end if
                        exit for
                Next
        end if
        wscript.quit
end sub

'------------------------------------------------------------
' Procédure de recherche et de renommage des dossiers dont la longueur du nom dépasse MaxNameLength
sub SearchAndRenLongName(NbreLignes)
On error resume next
dim ListeNewName()
redim ListeNewName(0)
NbreNewName=0
ParentRep=""
Err.Clear()

for x=1 to NbreLignes
        PosLastBSlash=InStrRev(listedossiers(0,x), "\")
        NomRep=mid(listedossiers(0,x),PosLastBSlash+1)
        LastParentRep=ParentRep
        ParentRep=mid(listedossiers(0,x), 1, PosLastBSlash)
        if ParentRep<>LastParentRep then redim ListeNewName(0) : NbreNewName=0
        if len(NomRep)>MaxNameLength then
                'renomme dossier et verif existe pas déja (avec gestion des noms déja renommés)
                id=0
                do 'recherche d'un nom unique
                        str_id="_" & Cstr(id)
                        newname=mid(NomRep,1,MaxNameLength-len(str_id)) & str_id
                        doublon=false
                        'on verifie que sur ce niveau ce nom n'a pas été déja utilisé pour les dossiers déja renommés
                        y=1
                        while y<=NbreNewName and doublon=false
                                if newname=ListeNewName(y) then doublon=true
                                y=y+1
                        wend

                        'on vérifie tous les noms de dossier de ce niveau
                        y=x-1
                        if y>0 then
                                TestPos=InStrRev(listedossiers(0,y), "\")
                                TestParentRep=mid(listedossiers(0,y), 1, TestPos)
                                while y>0 and TestParentRep=ParentRep and doublon=false
                                        OverName=mid(listedossiers(0,y),TestPos+1)
                                        if newname=overname then doublon=true
                                        y=y-1
                                        TestPos=InStrRev(listedossiers(0,y), "\")
                                        TestParentRep=mid(listedossiers(0,y), 1, TestPos)
                                wend
                        end if

                        y=x+1
                        if y<=NbreLignes then
                                TestPos=InStrRev(listedossiers(0,y), "\")
                                TestParentRep=mid(listedossiers(0,y), 1, TestPos)
                                while y<=NbreLignes and TestParentRep=ParentRep and doublon=false
                                        OverName=mid(listedossiers(0,y),TestPos+1)
                                        if newname=overname then doublon=true
                                        y=y+1
                                        TestPos=InStrRev(listedossiers(0,y), "\")
                                        TestParentRep=mid(listedossiers(0,y), 1, TestPos)
                                wend
                        end if
                        id=id+1
                loop  while doublon=true
                'newname est unique -> on affecte les changements à tous les dossiers concernés
                NbreNewName=NbreNewName+1
                redim preserve ListeNewName(NbreNewName)
                ListeNewName(NbreNewName)=newname
                if listedossiers(1,x)="" then
                        ParentRepSearch=listedossiers(0,x) & "\"
                        index=0
                        listedossiers(1,x)=ParentRep & newname
                else
                        ParentRepSearch=listedossiers(1,x) & "\"
                        index=1
                        PosLastBSlash1=InStrRev(listedossiers(1,x), "\")
                        listedossiers(1,x)=mid(listedossiers(1,x), 1, PosLastBSlash1) & newname
                end if
                'renomme tous les dossiers enfants (se trouvant obligatoirement aprés cet enregistrement)
                NbreChar=len(ParentRepSearch)
                for y=x+1 to NbreLignes
                        TestParentRep=mid(listedossiers(index,y), 1, NbreChar)
                        if TestParentRep=ParentRepSearch then 'dossier ayant la meme racine->change la racine
                                listedossiers(1,y)=listedossiers(1,x) & mid(listedossiers(index,y), NbreChar)
                        end if
                next
        end if
next
redim ListeNewName(0)
If Err.Number <> 0 Then ErrWrite("Une erreur s'est produite dans la fonction SearchAndRenLongName().")
end sub

'------------------------------------------------------------
' fonction permettant de supprimer tous les espaces droite et gauche de la variable chaine name
' et de remplacer par un '_' les espaces qu'il y a dans la chaine
function format(name)
On error resume next
        tempon1=trim(name)
        tempon2=""
        espace=false
        for pos=1 to len(tempon1)
                car = mid(tempon1, pos, 1)
                if car=" " then
                        if espace=false then
                                tempon2 = tempon2 & "_"
                                espace=true
                        end if
                else
                        espace=false
                        tempon2 = tempon2 & car
                end if
        next
        format = tempon2
end function

'------------------------------------------------------------
' fonction suppression arborescence répertoire, renvoi true si OK sinon false
function deltree(tree)
On error resume next
 Set objFSO = CreateObject("Scripting.FileSystemObject")
 deltree=true
 if not objFSO.FolderExists(tree) then exit function
 err.clear
 objFSO.DeleteFolder(tree)
 if Err.Number <> 0 then deltree=false
 exit function
end function

'------------------------------------------------------------
' fonction retournant un chemin court en utilisant un lecteur réseau.
function smallpath(path, lecteur, maxpath)
On error resume next
 set oNet = CreateObject("Wscript.Network")
 If objFSO.DriveExists(lecteur) Then oNet.RemoveNetworkDrive lecteur
 if path="" then
        Set oNet = nothing
        exit function
 end if

 if mid(path, 2, 1)=":" then path="\\127.0.0.1\" & mid(path, 1, 1) & "$" & mid(path,3) 'traitement d'un dossier local
 if len(path) <= maxpath then ' mappage de tout le chemin
        err.clear
        oNet.MapNetworkDrive lecteur, path
        If Err.Number = 0 Then smallpath = lecteur & "\"
 else
        if mid(path, maxpath+1, 1)="\" then
                firstpart=mid(path, 1, maxpath)
                secondpart=mid(path, maxpath+1)
        else
                k=InstrRev(path, "\", -1, 1)
                if k<6 then
                        Set oNet = nothing
                        exit function 'chemin trop court
                else
                        firstpart=mid(path, 1, k-1)
                        secondpart=mid(path, k)
                end if
        end if
        do while not objFSO.FolderExists(firstpart) 'vérification chemin existe pour montage lecteur réseau
                k=InstrRev(firstpart, "\", -1, 1)
                if k<6 then
                        Set oNet = nothing
                        exit function 'chemin trop court
                else
                        secondpart=mid(firstpart, k) & secondpart
                        firstpart=mid(firstpart, 1, k-1)
                end if
        loop
        'mappage d'une partie du path
        err.clear
        oNet.MapNetworkDrive lecteur, firstpart
        If Err.Number = 0 Then smallpath = lecteur & secondpart

 end if
 Set oNet = nothing
 FindLongPath=true
end function

'------------------------------------------------------------
' fonction retournant un chemin UNC d'un chemin ayant un lecteur réseau.
function retrievepath(path)
On error resume next
 set oNet = CreateObject("Wscript.Network")
 set colDrives = oNet.EnumNetworkDrives
 lecteur=lcase(mid(path, 1, 2))
 chemin=mid(path, 3)

 For k = 0 to colDrives.Count-1 Step 2
        if lcase(colDrives.Item(k))=lecteur then
                retrievepath=colDrives.Item(k+1) & chemin
                exit for
        end if
 Next
 Set oNet = nothing
 Set colDrives = nothing
end function

'------------------------------------------------------------
' fonction testant l'accés à tous les sous dossiers d'un dossier. (for each ne fonctionne qu'avec les dossiers accessible. Si dossier inaccessible -> le nbre d'iteration sera différent du nbre de dossier)
function  TestAccessSubfolder(collectionrep)
On error resume next
        cpt=0
        for each rep in collectionrep
             cpt=cpt+1
        next
        if cpt<>collectionrep.count then TestAccessSubfolder=false else TestAccessSubfolder=true
end function

'------------------------------------------------------------
' fonction testant l'accés à tous les fichiers d'un dossier. (for each ne fonctionne qu'avec les dossiers accessible. Si dossier inaccessible -> le nbre d'iteration sera différent du nbre de dossier)
function  TestAccessFile(collectionfile)
On error resume next
        cpt=0
        for each file in collectionfile
             cpt=cpt+1
        next
        if cpt<>collectionfile.count then TestAccessFile=false else TestAccessFile=true
end function

Conclusion :


Ce programme a un vécu de 3 ans.
j'ai corrigé les bugs pendant 1 ans (erreurs de programmation mais aussi bug window: les chemins long etc...)
Cela fait maintenant 2 ans qu'il tourne sans bug sur un réseau de 500pc 1500cptes 8serveurs

Reste à faire:
1)sauvegarde des ACL
2)interface web d'administration des sauvegardes avec:
configuration des variables du programme (MaxNameLength, racinesav, ScriptFilePath, DriveTemp)
création et configuration des taches planifiées pour la sauvegarde
3)Programme de restauration des données et des ACL

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.