#Script créé par Nicolas Lang - Sous licence CC-BY-SA #https://nicolaslang.fr if ([System.IntPtr]::Size -ne 4) { Write-Error "Ce script doit être lancé depuis un Powershell 32 bits (disponible dans %windir%\syswow64\WindowsPowershell)" Exit 3 } function Clean-Filename ($Filename=$(throw "Can't be empty")) { $invalidcharsforpath = [System.IO.Path]::GetInvalidFileNameChars() foreach ($char in $invalidcharsforpath) { $Filename = $Filename.replace("$char","") return $Filename } } $aclarray = New-Object System.Collections.ArrayList $errorarray = New-Object System.Collections.ArrayList #Le mot de passe à utiliser par l'identité proposée par Notes lorsque vous le lancez. Vous ne pouvez pas changer d'identité depuis ce script $passwordforactualaccount = "PASSW0RD" #Creating the Lotus object $lotus = New-Object -ComObject Lotus.Notessession try { #Ouverture de Notes avec l'identité par défaut et le mot de passe fourni $lotus.Initialize("$passwordforactualaccount") } catch { Write-Output "Impossible d'ouvrir Notes, mot de passe incorrect?." exit 2 } Write-Output "Logged as $($lotus.usernamelist.canonical)" <# Ce script enregistrera les données sur le Bureau. Vous pouvez changer la valeur pour un chemin régulier ou utiliser une valeur de cette list : Desktop Programs MyDocuments Personal (et bien d'autres...) #> $exportfolder = [Environment]::GetFolderPath("Desktop") Set-Location $exportfolder #Vous pouvez ajouter autant d'objets que vous le désirez dans la section $databasepath. Respectez juste la syntaxe et tout sera ok : #"server" : Le chemin vers le serveur Domino. Exemple : "\\DOMINO01" #"datapath" : Le chemin amenant versle repertoire des données de Domino, là ou sont stockés les fichiers NSF. Si vous utilisez un partage caché, ajoutez un ` avant le $. Cela échappera le caractère. Exemple : "d`$\domino\data\" #"splitpart" : Utilisé pour séparaer le repertoire racine du restant. Il s'agit souvent de "data", et cette section est utilisée pour Lotus, permettant à l'object COM de trouver la base dans son arborescence. # NE TERMINEZ PAS PAR Un \ . Si vous spécifiez une valeur avec un \ dedans, remplacez le par un double backslash \\. #"lotusdomainname" : Le nom que la methode getdatabase() va utiliser pour selectionner le serveur. $databasepath = @( [PSOBJECT]@{ "server"="\\DOMINO01" "datapath"="c`$\lotus\domino\data\" "splitpart"="data" "lotusdomainname"="domino01/Company France" } [PSOBJECT]@{ "server"="\\DOMINO03" "datapath"="d`$\lotus\domino\data\" "splitpart"="data" "lotusdomainname"="domino02/Company UK" } ) $resultsarray = @() #<# $id =0 $databasepath | foreach { #Pour chaque valeur dans databasepath, je joins "server" et "datapah' pour créer un chemin UNC pour l'analyse avec Robocopy $analysed = Join-Path $_.server $_.datapath #Le nom du fichier de log. $ID est incrementé, permettant de reconnaitre chaque entrée dans la variable $databasepath $logname = "robocopylog_$id.log" #Ajout de l'ID correspondante à l'entrée actuelle dans $databasepath $_ | Add-Member -MemberType NoteProperty -Name "logid" -Value $id $id++ $logname = Clean-Filename -Filename $logname try { New-Item -ItemType file -Name "$logname" -Force -ErrorAction Stop } catch { Write-Host "Impossible de créer le fichier de log : $logname" continue } #Lancement d'un nouveau processus Robocopy, qui scannera les dossiers à la recherche de nos précieux fichiers NSF, et enregistrant tout dans le fichier de log précedemment crée $results = Start-process "robocopy" -argumentlist "$analysed NULL *.nsf /NDL /NS /L /S /XJ /TS /NJS /NJH /UNILOG:$logname" -PassThru -Wait -WindowStyle Hidden #Les codes de sortie de Robocopy sont ok si en dessous de 7. Au dessus, une erreur s'est produite if ($results.ExitCode -gt 7) { Write-Warning "Erreur avec robocopy!" Exit 5 } } #> #On récupère les fichiers de log robocopy $loglist = Get-item "robocopylog_*.log" foreach ($log in $loglist) { #On se lance à la recherche du bon serveur et on collecte les valeurs demandées $thisserver = $null foreach ($server in $databasepath) { if ($log.name -eq "robocopylog_$($server.logid).log") { $thisserver = $server break } } if ($thisserver -eq $null) { Write-host "Impossible de trouver le serveur qui a créé $($log.name)" continue } else { #On récupère le contenu de chaque fichier... Get-Content $log | % { #Une petite regex pour retrouver le nom if ($_.trim() -match "(?[\\].*$)") { #Et on retrouve le chemin du fichier NSF sous un format que l'objet Lotus pourra comprendre $object = $null $cutindex = $Matches.file.IndexOf("$($thisserver.splitpart)\") $length = $Matches.file.Length try { $object = [PSOBJECT]@{ "server" = $thisserver.lotusdomainname "nsffile" = $Matches.file.Substring($cutindex,$length-$cutindex) } } catch { Write-Warning "Erreur lors de l'obtention des infos de $($matches.file)" } $resultsarray += $object } } } } #Maintenant que nous avons la liste des fichiers NSF, leur chemin, et le serveur domino qui est rattaché, nous pouvons collecter nos ACLs $progress = 0 foreach ($entry in $resultsarray) { Write-Progress -Activity "Analyse des ACL" -Status $entry.nsffile -PercentComplete $($progress/$($resultsarray.count)*100) $progress++ $index = 1 $aclobjectlist = @() #Vidage de $db à chaque passage, pour pouvoir vérifier si la propriété .ISOpen est $false (DB manquante) ou si $db n'existe pas (problem avec le chemin) $db = $null #Connexion à la DB $db = $lotus.GetDatabase($entry.server,$entry.nsffile) #On verifie que l'ouverture se fait correctement if ($db.IsOpen -eq $false -or $db -eq $null) { $message = $null switch ($db.isopen) { $null {$message = $($error[0].Exception.Message)} $false {$message = "Pas de base de données $($entry.nsffile) sur $($entry.server)"} } $errorarray.Add([PSCUSTOMOBJECT]@{ "Fichier" = $entry.nsffile -as [String] "Serveur" = $entry.server -as [String] "Erreur" = $message }) Write-Host "Impossible d'ouvrir $($entry.nsffile) sur $($entry.server)" continue } #On obtient la première ACL $acl = $db.ACL.GetFirstEntry() #On boucle tant qu'on trouve une autre ACL while ($acl -ne $null) { #On récupère si ca n'est pas un serveur et si c'est un groupe ou une personne if ($acl.IsServer -ne $true -and ($acl.isGroup -eq $true -or $acl.isperson -eq $true)) { #Je vérifie seulement les propriétés de création et suppression de documents. D'autres droits existent, que vous pouvez ajouter à la suite en utilisant la même syntaxe. $aclinfo = [PSCUSTOMOBJECT]@{ "Name" = $acl.Name "CanCreateDocuments" = $acl.CanCreateDocuments "CanDeleteDocuments" = $acl.CanDeleteDocuments } #Ajout de l'objet à la liste d'ACL $aclobjectlist += [pscustomobject]@{"Nom" =$acl.name;"Droits"=$aclinfo} $index++ } #On obtient la prochaine ACL ... et ainsi de suite $acl = $db.ACL.GetNextEntry($acl) } #Lorsque nous avons fini avec les ACL sur cette DB, on ajoute les résultats au tableau récaputilatif $aclarray.Add([PSCUSTOMOBJECT]@{ "Serveur" = $entry.server -as [String] "Fichier" = $entry.nsffile -as [String] "ACL" = $aclobjectlist | Sort-Object -Property "Nom"}) | Out-Null #Et on passe à la suivante } #On compte le maximum d'ACLs trouvées sur un DB. Cette valeur maximum sera utilisée pour ajouter des membres aux autres objets, d'avoir le même nombre partout afin d'avoir un fichier CSV à la fin. $max = 0 $aclarray | % { $count = $_.acl.count if ($count -gt $max) { $max = $count } } #Nouvel objet qui conservera toutes les données après formatage $exportableaclarray = New-Object System.Collections.ArrayList #On parcourt les résultats foreach ($entry in $aclarray) { #On crée une nouvelle ligne qui démarrera avec le nom du serveur, puis le nom de la base NSF $object = [PSCUSTOMOBJECT]@{ "Serveur" = $entry.serveur "Fichier" = $entry.Fichier } $index=1 #On ajoute des colonnes. D'abord le nom, puis les droits de création, ensuite de suppression pour chaque ACL trouvée foreach ($acl in $entry.acl) { $object | Add-Member -Name "Membre_$index" -MemberType NoteProperty -Value $acl.Nom $object | Add-Member -Name "Droits_Creation_membre_$index" -MemberType NoteProperty -Value $acl.Droits.CanCreateDocuments $object | Add-Member -Name "Droits_Suppression_membre_$index" -MemberType NoteProperty -Value $acl.Droits.CanDeleteDocuments $index++ } #Et on remplit le reste avec des valeurs vides jusqu'a ce que nous ayons le même nombre de colonnes que le fichier NSF avec le plus grand nombre d'ACL for ($i = $index;$i -le $max;$i++) { $object | Add-Member -Name "Membre_$i" -MemberType NoteProperty -Value $null $object | Add-Member -Name "Droits_Creation_membre_$i" -MemberType NoteProperty -Value $null $object | Add-Member -Name "Droits_Suppression_membre_$i" -MemberType NoteProperty -Value $null } $exportableaclarray.Add($object) | Out-Null } #Puis nous exportons les résultats $exportableaclarray | Export-Csv "$exportfolder\liste_acl_Notes.csv" -NoTypeInformation -Delimiter ";" -Encoding UTF8 #Et enfin les erreurs rencontrées $errorarray | Export-Csv "$exportfolder\erreuracl.csv" -NoTypeInformation -Delimiter ";" -Encoding UTF8