OVH Cloud OVH Cloud

sauvegarde des GPO modifiees

21 réponses
Avatar
Jean-Luc
Merci pour ton script
J'ai corrig=E9 2 bugs :( avec beaucoup de mal , je suis completement
novice)
1=B0
arrGPO (2) =3D Replace ( _
> oXml.getElementsByTagName ("ModifiedTime")(0).text, _
> "T", " ")

> cette ligne supprimait la lettre T, du coup le format n etait pas bon voi=
ci ma ligne
arrGPO (2) =3D Left (oXml.getElementsByTagName ("ModifiedTime")(0).text,
10)

2=B0
a la fin du script
j'ai mont=E9 la ligne :
>WScript.Echo "Backup ID : " & oFolder.Name & " (deleted)"
au dessus de
> oFolder.Delete (True) "car la WScript.Echo etait impossible o=
Folder etait efface avt , je suppose"

et du coup le script s'execute correctement, par contre j'avais du mal
m exprimer car
je voulais supprimer les gpo dont le champs modified time est identique
.

explication :
lundi : GPO1 je la sauvegarde > BCK1
mardi : GPO1 je la resauvegarde > BCK2
mercredi : GPO1 je la modifie > GPO1a je sauvegarde > BCK3
jeudi : GPO1a je la sauvegarde > BCK4

actuellement le script garde BCK4, c est comme si je supprimais mon
repertoire sauvegarde
et je reexecutais backupall :-)

je voudrais que le script supprime :
BCK2 car "modified time" est identique =E0 BCK1
BCK4 car "modified time" est identique =E0 BCK3

au finale je retrouve toutes mes versions de GPO1, GPO1a .

Voici le script :
Option Explicit
' d=E9claration des variables
Dim oXml, oFs, oDic, oRootFolder, oFolder
Dim colFolders
Dim arrGPO (5), arrTemp
Dim strGPOId, strKey, strBackupFolder
Dim bBackup


' lecture du dossier racine pass=E9 comme argument
' ce dossier contient les backup id
strBackupFolder =3D WScript.Arguments (0)


' initialisation des objets
set oXml =3D CreateObject("Microsoft.XMLDOM")
set oFS =3D CreateObject ("Scripting.FileSystemObject")
Set oDic =3D CreateObject ("Scripting.Dictionary")

' ouverture du dossier racine
Set oRootFolder =3D oFs.GetFolder (strBackupFolder)

' lecture des sous dossiers (backup id)
Set colFolders =3D oRootFolder.SubFolders

' =E9num=E9ration des backup id
For Each oFolder In ColFolders
' chargement du fichier xml propre =E0 la sauvegarde
' le fichier gpreport.xml est automatiquement g=E9n=E9r=E9
' lors de la sauvegarde de la gpo
oXml.Async=3DFalse
oXml.Load (strBackupFolder & _
"\" & oFolder.Name & _
"\" & "GPReport.xml")
' lecture des valeurs xml via le parser
strGPOId =3D oXml.getElementsByTagName ("Identifier")(1).text
arrGPO (0) =3D oXml.getElementsByTagName ("Name")(0).text
arrGPO (1) =3D oFolder.Name
arrGPO (2) =3D Left (oXml.getElementsByTagName
("ModifiedTime")(0).text, 10)


' calcul d'un timestamp Epoch
arrGPO (3) =3D DateDiff ("S", "1990-01-01", arrGPO (2))
arrGPO (4) =3D oFolder.DateCreated
' stockage des valeurs xml dans un hash
If Not oDic.Exists (strGPOId) Then
oDic (strGPOId) =3D Join (arrGPO, "~")
Else
' la gpo a d=E9j=E0 =E9t=E9 sauvegard=E9e (doublon)
' la plus r=E9cente "gagne"
' utilisation du timestamp calcul=E9 pr=E9c=E9demment
arrTemp =3D Split (oDic (strGPOId), "~")
If CLng (arrGPO (3)) > CLng (arrTemp (3)) Then
oDic (strGPOId) =3D Join (arrGPO, "~")
End If
End If
Next
' les sauvegardes les plus r=E9centes sont stock=E9es dans le hash
' suppression des backup obsol=E8tes et affichage du r=E9sum=E9
For Each oFolder In colFolders
bBackup =3D False
For Each strKey In oDic.Keys
arrTemp =3D Split (oDic (strKey), "~")
If arrTemp (1) =3D oFolder.Name Then
WScript.Echo "GPO ID : " & strkey
WScript.Echo "Modified : " & arrTemp (2)
WScript.Echo "GPO Name : " & arrTemp (0)
WScript.Echo "Backup ID : " & arrTemp (1)
WScript.Echo "Timestamp : " & arrTemp (4)
WScript.Echo ""
bBackup =3D True
Exit For
End If
Next
If bBackup =3D False Then
' le backup est obsol=E8te
' suppression du sous dossier (backup id)
WScript.Echo "Backup ID : " & oFolder.Name & " (deleted)"
oFolder.Delete (True)
WScript.Echo ""
End If
Next

10 réponses

1 2 3
Avatar
jbongran
Gilles LAURENT wrote:
"Gilles LAURENT" a écrit dans le message de
news:

Ci-dessous une version optimisée.
Testé avec 80 GPO (160 backupId)
Temps de traitement : 20 s (suppression de 70 dossiers)

Je serai intéressé de connaitre le temps de traitement pour de gros
volumes.

--- Coupez ici : cleanBackupFolder.vbs ---

Option Explicit

' déclaration des variables
Dim oFs, oBkpInfo, oDic, oSh, oExec, oFolder, oXml
Dim arrBackupId
Dim strBkpFolder, strBackupId
Dim i, j

' définition des constantes
Const strFilter = "%comspec% /c dir /b /a:d /o:d /t:c "

' lecture du dossier des sauvegardes gpmc
' le dossier est passé comme argument
strBkpFolder = WScript.Arguments (0)

' initialisation des objets
set oFs = CreateObject ("Scripting.FileSystemObject")
Set oBkpInfo = CreateObject ("Scripting.Dictionary")
Set oDic = CreateObject ("Scripting.Dictionary")
Set oSh = CreateObject ("WScript.Shell")
set oXml = CreateObject ("Microsoft.XMLDOM")

' lecture des backupId triés par ordre de création
' en cas de doublon, cela permet de conserver la sauvegarde
' la plus ancienne et donc supprimer la plus récente
Set oExec = oSh.Exec (strFilter & _
Chr (34) & strBkpFolder & Chr (34))
arrBackupId = Split (oExec.StdOut.ReadAll, VBCrLf)

' lecture des fichiers gpreport.xml
' et stockage des informations dans un hash
For i = 0 To UBound (arrBackupId) - 1
oBkpInfo (arrBackupId (i)) = GetBkpInfo (arrBackupId (i))
Next

' recherche des doublons
For i = 0 To UBound (arrBackupId) - 1
For j = i + 1 To UBound (arrBackupId) - 1
If _
oBkpInfo (arrBackupId (i)) = _
oBkpInfo (arrBackupId (j)) _
Then
oDic (arrBackupId (j)) = oBkpInfo (arrBackupId (j))
End If
Next
Next

' suppression des doublons
For Each strBackupId In oDic.Keys
Set oFolder = oFs.GetFolder (strBkpFolder & "" & strBackupId)
oFolder.Delete (True)
WScript.Echo strBackupId & " (deleted)"
Next

' lecture du fichier gpreport.xml
Function GetBkpInfo (strBackupId)

oXml.Asyncúlse
oXml.Load (strBkpFolder & "" & strBackupId & "" & "gpreport.xml")
GetBkpInfo = _
oXml.getElementsByTagName ("Identifier/Identifier")(0).text & _
oXml.getElementsByTagName ("ModifiedTime")(0).text

End Function

--- Coupez ici : cleanBackupFolder.vbs ---


My 2 cents:
' suppression des doublons
For Each strBackupId In oDic.Keys
oFs.DeleteFolder (strBkpFolder & "" & strBackupId, True)
WScript.Echo strBackupId & " (deleted)"
Next

Il eut été aussi possible de creer un recordset deconnecté (disconnected
recordset) permettant avec une reqête triée du style "select
distinct....order by... " de simplifier la manip pour exclure les doublons.
J'ai un bout de code comme ça en prod sur un IIS avec de gros volumes de
datas en provenance d'un AS400, le but était de prendre des datas de deux
"tables" différentes mais qui pouvaient contenir tout ou partie des
enregistrement dans les deux. Une requête sur les deux tables (style
jointure) ou une procédure stockée n'était pas acceptable à l'époque.

Avatar
Gilles LAURENT
"jbongran" a écrit dans le message de
news:

Bonsoir,

| My 2 cents:
| ' suppression des doublons
| For Each strBackupId In oDic.Keys
| oFs.DeleteFolder (strBkpFolder & "" & strBackupId, True)
| WScript.Echo strBackupId & " (deleted)"
| Next

Bien vu ;-)

| Il eut été aussi possible de creer un recordset deconnecté
| (disconnected recordset) permettant avec une reqête triée du style
| "select distinct....order by... " de simplifier la manip pour exclure
| les doublons.

J'ai pensé à cette technique mais le challenge consiste à supprimer les
doublons en préservant toutefois le plus ancien backupId (versionning).
Le plus ancien backupId étant déterminé par sa date de création (date de
création du dossier). Auriez-vous un peu de temps pour écrire et Poster
une version utilisant cette technique adaptée au contexte GPMC ? Moi, je
suis preneur ;-)

Quoi qu'il en soit, merci pour ce retour.

--
Gilles LAURENT
Me contacter : http://cerbermail.com/?zoTY7ZkLcD
Avatar
jbongran
Gilles LAURENT wrote:
"jbongran" a écrit dans le message de
news:

Bonsoir,

My 2 cents:
' suppression des doublons
For Each strBackupId In oDic.Keys
oFs.DeleteFolder (strBkpFolder & "" & strBackupId, True)
WScript.Echo strBackupId & " (deleted)"
Next


Bien vu ;-)

Il eut été aussi possible de creer un recordset deconnecté
(disconnected recordset) permettant avec une reqête triée du style
"select distinct....order by... " de simplifier la manip pour exclure
les doublons.


J'ai pensé à cette technique mais le challenge consiste à supprimer
les doublons en préservant toutefois le plus ancien backupId
(versionning). Le plus ancien backupId étant déterminé par sa date de
création (date de création du dossier). Auriez-vous un peu de temps
pour écrire et Poster une version utilisant cette technique adaptée
au contexte GPMC ? Moi, je suis preneur ;-)

Quoi qu'il en soit, merci pour ce retour.


Un début pour le principe du recordset deconnecté, mais là je sèche sur le
filter avec un distinct ;-)
Je n'ai pas compris le principe du versionning, s'agit-il de la date de
création du dossier, ou de la date dans le fichier gpreport.xml ? Je ne
connait rien au contexte GPMC.

Option Explicit

Dim oFs, strBkpFolder, oFolders, FolderCollection, SF, Rs, oXml
strBkpFolder = WScript.Arguments (0)
set oFs = CreateObject ("Scripting.FileSystemObject")
set oXml = CreateObject ("Microsoft.XMLDOM")

Const adUseClient = 3
Const adOpenStatic = 3
Const adVarChar = 200
Set Rs = CreateObject("ADODB.RECORDSET")
Rs.CursorLocation = adUseClient
Rs.CursorType = adOpenStatic
Rs.Fields.Append "foldername", adVarChar, 200
Rs.Fields.Append "DateCre", adVarChar, 200
Rs.Fields.Append "DateXml", adVarChar, 200
Rs.open

Sub AddEnreg(strFold, strDateCre, strDateXml)
Rs.addnew
Rs.Fields("foldername").Value = strFold
Rs.Fields("DateCre").Value = strDateCre
Rs.Fields("DateXml").Value = strDateXml
End Sub

Set oFolders = oFs.GetFolder(strBkpFolder)
Set FolderCollection = oFolders.SubFolders
For Each SF in FolderCollection
Call AddEnreg(SF.name, SF.DateCreated, GetBkpInfo(SF.name))
Next

Rs.Sort = "DateCre DESC"
Rs.MoveFirst
Do While Not Rs.EOF
' Suppr des fichiers....
Rs.MoveNext
Loop

Function GetBkpInfo (strBackupId)
oXml.Asyncúlse
oXml.Load (strBkpFolder & "" & strBackupId & "" & "gpreport.xml")
GetBkpInfo = _
oXml.getElementsByTagName ("Identifier/Identifier")(0).text & _
oXml.getElementsByTagName ("ModifiedTime")(0).text
End Function


Avatar
Jean-Luc
Bonjour Gilles ,

je ne comprends pas tes scripts fonctionnaient tres bien mais
maintenant sur le cleanbackupfolder.vbs et sur la version "optimisé"
j'ai un message d'erreur :

Erreur d'execution Microsoft VBScript : Objet requis :
'oXml.getElement ByTagnName(...)(...)'

pourtant j execute : cscript cleanbackupfolder.vbs
e:datagposauvegarde

Qu est ce que j ai bien pu modifier ?




Gilles LAURENT wrote:
"jbongran" a écrit dans le message de
news:

Bonsoir,

My 2 cents:
' suppression des doublons
For Each strBackupId In oDic.Keys
oFs.DeleteFolder (strBkpFolder & "" & strBackupId, True)
WScript.Echo strBackupId & " (deleted)"
Next


Bien vu ;-)

Il eut été aussi possible de creer un recordset deconnecté
(disconnected recordset) permettant avec une reqête triée du style
"select distinct....order by... " de simplifier la manip pour exclure
les doublons.


J'ai pensé à cette technique mais le challenge consiste à supprim er
les doublons en préservant toutefois le plus ancien backupId
(versionning). Le plus ancien backupId étant déterminé par sa dat e de
création (date de création du dossier). Auriez-vous un peu de temps
pour écrire et Poster une version utilisant cette technique adaptée
au contexte GPMC ? Moi, je suis preneur ;-)

Quoi qu'il en soit, merci pour ce retour.


Un début pour le principe du recordset deconnecté, mais là je sèc he sur le
filter avec un distinct ;-)
Je n'ai pas compris le principe du versionning, s'agit-il de la date de
création du dossier, ou de la date dans le fichier gpreport.xml ? Je ne
connait rien au contexte GPMC.

Option Explicit

Dim oFs, strBkpFolder, oFolders, FolderCollection, SF, Rs, oXml
strBkpFolder = WScript.Arguments (0)
set oFs = CreateObject ("Scripting.FileSystemObject")
set oXml = CreateObject ("Microsoft.XMLDOM")

Const adUseClient = 3
Const adOpenStatic = 3
Const adVarChar = 200
Set Rs = CreateObject("ADODB.RECORDSET")
Rs.CursorLocation = adUseClient
Rs.CursorType = adOpenStatic
Rs.Fields.Append "foldername", adVarChar, 200
Rs.Fields.Append "DateCre", adVarChar, 200
Rs.Fields.Append "DateXml", adVarChar, 200
Rs.open

Sub AddEnreg(strFold, strDateCre, strDateXml)
Rs.addnew
Rs.Fields("foldername").Value = strFold
Rs.Fields("DateCre").Value = strDateCre
Rs.Fields("DateXml").Value = strDateXml
End Sub

Set oFolders = oFs.GetFolder(strBkpFolder)
Set FolderCollection = oFolders.SubFolders
For Each SF in FolderCollection
Call AddEnreg(SF.name, SF.DateCreated, GetBkpInfo(SF.name))
Next

Rs.Sort = "DateCre DESC"
Rs.MoveFirst
Do While Not Rs.EOF
' Suppr des fichiers....
Rs.MoveNext
Loop

Function GetBkpInfo (strBackupId)
oXml.Asyncúlse
oXml.Load (strBkpFolder & "" & strBackupId & "" & "gpreport.xml")
GetBkpInfo = _
oXml.getElementsByTagName ("Identifier/Identifier")(0).text & _
oXml.getElementsByTagName ("ModifiedTime")(0).text
End Function




Avatar
Gilles LAURENT
"Jean-Luc" a écrit dans le message de
news:
| Bonjour Gilles ,

Bonjour Jean-Luc,

| je ne comprends pas tes scripts fonctionnaient tres bien mais
| maintenant sur le cleanbackupfolder.vbs et sur la version "optimisé"
| j'ai un message d'erreur :
|
| Erreur d'execution Microsoft VBScript : Objet requis :
| 'oXml.getElement ByTagnName(...)(...)'

La variable oXml doit être déclaré :

<...>
' déclaration des variables
Dim oFs, oBkpInfo, oDic, oSh, oExec, oFolder, oXml
<...>

Ne sachant pas ce que vous avez touché, le plus simple est de reprendre
le script dans son intégralité.

--
Gilles LAURENT
Me contacter : http://cerbermail.com/?zoTY7ZkLcD
Avatar
Jean-Luc
J'ai trouvé le probleme :
dans certain dossier BackupID le fichier gpresult.xml est vide (1Ko)
quand je regarde mes logs
j ai des messages du genre :
Backed up GPO 'S,curit, des groupes restreints' with the following
properties:


GPO ID: {00B24853-299D-4C8F-B0F4-857F9F0827BF}
Timestamp: 12/10/2006 12:54:04
Backup ID: {DFDBB030-B772-4E74-A024-38DF84B4D935}

Le rapport sur cet objet GPO n'a pas pu ˆtre cr,,. La sauvegarde
ne contiendra aucun rapport des paramŠtres.
D,tailsÿ: Le fichier sp,cifi, est introuvable.

maintenant il faut que je trouve pourquoi le 1° script n arrive pas à
créer le fichier gpresult.



"Jean-Luc" a écrit dans le message de
news:
| Bonjour Gilles ,

Bonjour Jean-Luc,

| je ne comprends pas tes scripts fonctionnaient tres bien mais
| maintenant sur le cleanbackupfolder.vbs et sur la version "optimisé"
| j'ai un message d'erreur :
|
| Erreur d'execution Microsoft VBScript : Objet requis :
| 'oXml.getElement ByTagnName(...)(...)'

La variable oXml doit être déclaré :

<...>
' déclaration des variables
Dim oFs, oBkpInfo, oDic, oSh, oExec, oFolder, oXml
<...>

Ne sachant pas ce que vous avez touché, le plus simple est de reprendre
le script dans son intégralité.

--
Gilles LAURENT
Me contacter : http://cerbermail.com/?zoTY7ZkLcD


Avatar
Gilles LAURENT
"Jean-Luc" a écrit dans le message de
news:
| J'ai trouvé le probleme :
| dans certain dossier BackupID le fichier gpresult.xml est vide (1Ko)
| quand je regarde mes logs

Merci pour ce retour.
Il est donc nécessaire de mettre en oeuvre une gestion d'exceptions ;-)

--
Gilles LAURENT
Me contacter : http://cerbermail.com/?zoTY7ZkLcD
Avatar
Gilles LAURENT
"jbongran" a écrit dans le message de
news:%

Bonsoir,

| Un début pour le principe du recordset deconnecté, mais là je sèche
| sur le filter avec un distinct ;-)

J'ai trouvé un peu de temps pour creuser cette piste. C'est ici :
http://glsft.free.fr/index.php?option=com_content&task=view&id &Itemid3

--
Gilles LAURENT
http://glsft.free.fr
Me contacter : http://cerbermail.com/?zoTY7ZkLcD
Avatar
jbongran
Gilles LAURENT wrote:
"jbongran" a écrit dans le message de
news:%

Bonsoir,

Un début pour le principe du recordset deconnecté, mais là je sèche
sur le filter avec un distinct ;-)


J'ai trouvé un peu de temps pour creuser cette piste. C'est ici :
http://glsft.free.fr/index.php?option=com_content&task=view&id &Itemid3


Joli ;-)
Et question perfs, des retours ?
Il eut été aussi possible, une fois les enregistrements dans le recordset,
de sauvegarder ce dernier en tant que fichier xml, ce qui aurait permi de
l'ouvrir avec une requête sql utilisant le select distinct..


Avatar
Gilles LAURENT
"jbongran" a écrit dans le message de
news:%23Y$

Bonsoir,

| Joli ;-)

Merci !

| Et question perfs, des retours ?

Lors de mes tests, je n'ai pas noté véritablement de gain en
performances par rapport à la version avec tri à bulle sauf dans le cas
de figure ou il existe plusieurs doublons pour un même backupId.

| Il eut été aussi possible, une fois les enregistrements dans le
| recordset, de sauvegarder ce dernier en tant que fichier xml, ce qui
| aurait permi de l'ouvrir avec une requête sql utilisant le select
| distinct..

Non, cela ne fonctionne pas comme cela. Il n'est pas possible de
réaliser des requêtes sql sur un recordset. Les requêtes sql ne peuvent
être utilisées que sur des bases de données (on doit obligatoirement
disposer d'un objet connexion). En règle générale, un recordset contient
les enregistrements issus d'une requête sql ou alors des enregistrements
"fabriqués" dans le cas d'un recordset initialement déconnecté. Il est
en effet possible de sauvegarder le recordset dans un fichier xml
néanmoins ceci n'a que peu d'intêret ici car la méthode 'open' ne
permettra que de le recharger tel quel. La seule technique consiste donc
à filtrer les enregistrements via la propriété 'filter'. Grâce à ce
filtre, il est possible de masquer temporairement certains
enregistrements du recordset dans le but de réaliser un traitement sur
des enregistrements spécifiques.

--
Gilles LAURENT
http://glsft.free.fr
Me contacter : http://cerbermail.com/?zoTY7ZkLcD
1 2 3