logo_mini_comments

Sans partage, la connaissance n'est rien !

Fil de navigation

Ce script créé par mes soins permet de calculer la taille des dossiers et des sous-dossiers souhaités et d'exporter les résultats dans un fichier .csv (trié par taille).

 

Fonctionnalités :

  • Calculer la taille des dossiers et des sous-dossiers souhaités (Colonnes récupérées : FolderName, Size (Bytes), Size (MB), Size (GB), CreationTime, LastWriteTime)
  • Exporter les données dans un fichier .csv (trié par taille)
  • Exporter les données dans un rapport HTML (trié par taille)

 

Utilisation :

  • Compléter la variable suivante dans le script :
    • $BasePath = "D:\Scripts" (Chemin d'accès aux dossiers à calculer)

 

Screenshot :

 

Code du script :

<#
.SYNOPSIS
    Displays folders list with their size
.DESCRIPTION
    Displays and export folders list with their size
.NOTES
    File name : Get-FolderSize.ps1
    Author : Pierre JACQUOT
    Date : 19/07/2017
    Version : 1.0
.LINK
    Website : https://www.pierrejacquot.yo.fr
    Reference : https://www.pierrejacquot.yo.fr/index.php/scripts/39-script-get-foldersize
#>

Clear-Host

$StartTime = Get-Date -Format "dd/MM/yyyy HH:mm:ss"
[string]$Hostname = [Environment]::MachineName
[string]$Login = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
[string]$Workfolder = Split-Path $MyInvocation.MyCommand.Path
[string]$Date = Get-Date -UFormat "%Y-%m-%d"
[string]$BasePath = "D:\Scripts"
[string]$CSVFile = $Workfolder + "\$Date-Folders-Export.csv"
[string]$ReportFile = $Workfolder + "\$Date-Folders-Report.html"
[array]$AllFolders = Get-Childitem -Path $BasePath -Directory -Force
[int]$FolderNumbers = $AllFolders.Count
[System.Collections.ArrayList]$FolderList = @()
[string]$Activity = "Trying to launch the export of [$FolderNumbers] folder(s)"
[int]$Step = 1
[string]$Title = "[$Date] - Folder(s) size report on : $Hostname"

Write-Host "Get-FolderSize :" -ForegroundColor Black -BackgroundColor Yellow
Write-Host "Launching the export of [$FolderNumbers] folder(s)." -ForegroundColor Cyan
Write-Host "`r"

If ($FolderNumbers -eq 0) {
    Write-Warning "There is no folder in $BasePath"
}
Else {
    ForEach ($Folder in $AllFolders) {
        [string]$Status = "Processing [$Step] of [$FolderNumbers] - $(([math]::Round((($Step)/$FolderNumbers*100),0)))% completed"
        [string]$CurrentOperation = "Calculating size on folder : $Folder"
        Write-Progress -Activity $Activity -Status $Status -CurrentOperation $CurrentOperation -PercentComplete ($Step/$FolderNumbers*100)
        $Step++

        [string]$FolderFullPath = $null
        $FolderObject = $null
        $FolderCreationTime = $null
        $FolderLastWriteTime = $null
        [string]$FolderSizeInMB = $null
        [string]$FolderSizeInGB = $null
        [string]$FolderBaseName = $null

        $FolderFullPath = $Folder.FullName
        $FolderBaseName = $Folder.BaseName
        $FolderCreationTime = $Folder.CreationTime
        $FolderLastWriteTime = $Folder.LastWriteTime
        [array]$FolderSize = Get-Childitem -Path $FolderFullPath -Recurse -Force -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum -ErrorAction SilentlyContinue
        $FolderSizeInMB = "{0:N3}" -f ($FolderSize.Sum / 1MB)
        $FolderSizeInGB = "{0:N3}" -f ($FolderSize.Sum / 1GB)

        $FolderObject = [PSCustomObject]@{
            FolderName = $FolderBaseName
            "Size (Bytes)" = $FolderSize.Sum
            "Size (MB)" = $FolderSizeInMB
            "Size (GB)" = $FolderSizeInGB
            CreationTime = $FolderCreationTime
            LastWriteTime = $FolderLastWriteTime
        }
        $FolderList.Add($FolderObject) | Out-Null
    }
}

[array]$FoldersList = $FolderList | Sort-Object "Size (Bytes)" -Descending
$FoldersList | Format-Table -AutoSize
$FoldersList | Export-Csv -Path $CSVFile -NoTypeInformation -Delimiter ";" -Encoding UTF8

[string]$TotalSizeInBytes = "{0:N3} Bytes" -f ((Get-ChildItem -Path $BasePath -Recurse -Force | Measure-Object -Property Length -Sum).Sum)
[string]$TotalSizeInMB = "{0:N3} MB" -f ((Get-ChildItem -Path $BasePath -Recurse -Force | Measure-Object -Property Length -Sum).Sum / 1MB)
[string]$TotalSizeInGB = "{0:N3} GB" -f ((Get-ChildItem -Path $BasePath -Recurse -Force | Measure-Object -Property Length -Sum).Sum / 1GB)

$EndTime = Get-Date -Format "dd/MM/yyyy HH:mm:ss"
[decimal]$Duration = [math]::Round((New-TimeSpan -Start $StartTime -End $EndTime).TotalSeconds,2)

[string]$PreContent = "<h1>$Title</h1>
<h2>Number of folder(s) : <span class='PostContentBlue'>$FolderNumbers</span></h2>"
[string]$PostContent = "<p>Total size : <span class='PostContentBlue'><strong>$TotalSizeInBytes</strong></span> - <span class='PostContentBlue'><strong>$TotalSizeInMB</strong></span> - <span class='PostContentBlue'><strong>$TotalSizeInGB</strong></span> on <span class='PostContentBlue'><strong>$BasePath</strong></span></p>
<p id='PostContent'>Script launched from : <span class='PostContentBlue'>$Hostname</span><br/>
By : <span class='PostContentBlue'>$Login</span><br/>
Path : <span class='PostContentBlue'>$Workfolder</span><br/>
CSV file : <span class='PostContentBlue'>$(Split-Path $CSVFile -Leaf)</span><br/>
Report file : <span class='PostContentBlue'>$(Split-Path $ReportFile -Leaf)</span><br/>
Start time : <span class='PostContentBlue'>$StartTime</span><br/>
End time : <span class='PostContentBlue'>$EndTime</span><br/>
Duration : <span class='PostContentBlue'>$Duration</span> second(s)</p>"
[string]$Report = $FoldersList | ConvertTo-Html -As Table -CssUri ".\Style.css" -Title $Title -PreContent $PreContent -PostContent $PostContent
$Report | Out-File -FilePath $ReportFile -Encoding utf8

Write-Host "Total size : $TotalSizeInBytes - $TotalSizeInMB - $TotalSizeInGB on [$BasePath]" -ForegroundColor Cyan

Write-Host "`r"
Write-Host "Script launched from : " -NoNewline; Write-Host $Hostname -ForegroundColor Red
Write-Host "By : " -NoNewline; Write-Host $Login -ForegroundColor Red
Write-Host "Path : " -NoNewline; Write-Host $Workfolder -ForegroundColor Red
Write-Host "CSV file : " -NoNewline; Write-Host (Split-Path $CSVFile -Leaf) -ForegroundColor Red
Write-Host "Report file : " -NoNewline; Write-Host (Split-Path $ReportFile -Leaf) -ForegroundColor Red
Write-Host "Start time : " -NoNewline; Write-Host $StartTime -ForegroundColor Red
Write-Host "End time : " -NoNewline; Write-Host $EndTime -ForegroundColor Red
Write-Host "Duration : " -NoNewline; Write-Host $Duration -ForegroundColor Red -nonewline; Write-Host " second(s)"
Write-Host "`r"

 

Cliquer ici pour visualiser un exemple du rapport Folders-Report.html créé automatiquement depuis mon poste.

 

Cliquer ici pour télécharger le fichier de style css.

 

Cliquer ici pour télécharger le script.

 

One-Liner :

#OL01 - Afficher la taille (en GB) du dossier "C:\Program Files"

"{0:N2} (GB)" -f ((Get-ChildItem -Path "C:\Program Files" -Recurse | Measure-Object -Property Length -Sum).Sum / 1GB)

 

Ce script créé par mes soins permet de copier des dossiers en masse sur un espace de stockage avec la création d'un fichier qui log les actions effectuées.

 

Fonctionnalités :

  • Copier des dossiers sur un espace de stockage
  • Création d'un fichier de logs horodatés (Copy-File)

 

Ce script utilise Robocopy (ou Robust File Copy) qui est un utilitaire en ligne de commande permettant de faire de la réplication de dossiers et fichiers. Cet utilitaire a été introduit dans le "Resource Kit" de Windows Server 2003 et est intégré par défaut à Windows depuis Windows Server 2008 et Windows Vista, il est présent sur toute les versions suivantes que ce soit les versions poste de travail (Windows 7, 8, 8.1 et 10) ou les versions serveur (Windows Server 2008 R2, 2012, 2012 R2). Il est ainsi totalement GRATUIT.

 

La dernière version de Robocopy est la version 6.2 qui est fourni depuis Windows 8 et Windows Server 2012.

 

Robocopy est comparable à la commande XCOPY mais possède plus d'options qui offrent plus de possibilités pour la configuration de scripts de réplication ou sauvegarde.

 

Robocopy possède de nombreuses fonctionnalités qui sont très appréciées car elle sont supérieures aux commandes internes COPY ou XCOPY de Windows, en particulier :

  • Une tolérance aux coupures réseau et une reprise une fois la connexion rétablie
  • La conservation des attributs et des informations d'appartenances des fichiers ou dossiers (créateur, propriétaire, ACL NTFS, informations d'audit)
  • Un mode "mirroir" qui permet de mettre en place une synchronisation entre l'emplacement source et l'emplacement de destination
  • Une copie différentielle qui ne copie que les fichiers n'existant pas sur l'emplacement de destination (vérification grâce à la taille et aux métadonnées des fichiers)
  • Un indicateur de progression dans l'invite de commande
  • Des copies effectuées en parallèle (multithread, disponible depuis WIndows 7)

 

Documentation complète :

-------------------------------------------------------------------------------
   ROBOCOPY   ::   Copie de fichiers robuste pour Windows     
-------------------------------------------------------------------------------

  Début : Tue Jun 13 22:39:55 2017

              Syntaxe :: ROBOCOPY source destination [fichier [fichier]...] [options]

             source :: répertoire source (lecteur:\chemin ou \\serveur\partage\chemin).
        destination :: rép. de destination (lecteur:\chemin ou \\serveur\partage\chemin).
               fichier :: fichier(s) à copier (noms/caractères génériques : valeur par défaut "*.*").

::
:: Options de copie :
::
                 /S :: copie les sous-répertoires non vides uniquement.
                 /E :: copie les sous-répertoires, y compris les vides.
             /LEV:n :: copie uniquement les n premiers niveaux de l’arborescence source.

                 /Z :: copie les fichiers en mode de redémarrage.
                 /B :: copie les fichiers en mode de sauvegarde.
                /ZB :: utilise le mode de redémarrage ; si l’accès est refusé, utilise le mode de sauvegarde.
            /EFSRAW :: copie tous les fichiers chiffrés en mode EFS RAW.

  /COPY:indicateurscopie :: spécifie les éléments à copier pour les fichiers (/COPY:DAT par défaut).
                       (indicateurscopie : D=Données, A=Attributs, T=horodaTages).
                       (S=Sécurité=ACL NTFS, O=infos prOpriétaire, U=infos d’aUdit).

           /DCOPY:T :: copie les horodatages de répertoire.

               /SEC :: copie des fichiers avec sécurité (équivaut à /COPY:DATS).
           /COPYALL :: copie toutes les infos de fichiers (équivaut à /COPY:DATSOU).
            /NOCOPY :: ne copie aucune info de fichier (utile avec /PURGE).

            /SECFIX :: corrige la sécurité de tous les fichiers, même les fichiers ignorés.
            /TIMFIX :: corrige les horodatages de tous les fichiers, même les fichiers ignorés.

             /PURGE :: supprime les fichiers/répertoires de destination qui n’existent plus dans la source.
               /MIR :: met en MIRoir une arborescence (équivaut à /E plus /PURGE).

               /MOV :: déplace les fichiers (les supprime de la source après la copie).
              /MOVE :: déplace les fichiers ET les répertoires (les supprime de la source après la copie).

     /A+:[RASHCNET] :: ajoute les Attributs donnés aux fichiers copiés.
     /A-:[RASHCNET] :: supprime les Attributs donnés des fichiers copiés.

            /CREATE :: crée une arborescence et des fichiers de longueur nulle uniquement.
               /FAT :: crée des fichiers de destination au format de nom 8.3 FAT uniquement.
               /256 :: désactive la prise en charge des chemins d’accès très longs (> 256 caractères).

             /MON:n :: source du moniteur ; réexécuté lorsque plus de n modifications sont observées.
             /MOT:m :: source du moniteur ; réexécuté après m minutes en cas de modification.

      /RH:hhmm-hhmm :: heures d’exécution : heures auxquelles de nouvelles copies peuvent être lancées.
                /PF :: vérifie les heures d’exécution Par Fichier (et non par passage).

             /IPG:n :: délai entre les paquets (ms) pour libérer la bande passante sur les lignes bas débit.

                /SL:: copie les liens symboliques par opposition à la cible.

            /MT[:n] :: Effectuer des copies multi-thread avec n threads (par défaut, 8).
                       n doit être au moins égal à 1 et pas supérieur à 128.
                       Cette option est incompatible avec les options /IPG et /EFSRAW.
                       Rediriger la sortie avec l’option /LOG pour de meilleures performances.

::
:: Options de sélection des fichiers :
::
                 /A :: copie uniquement les fichiers où l’attribut Archive est défini.
                 /M :: copie uniquement les fichiers où l’attribut Archive est défini et le réinitialise.
    /IA:[RASHCNETO] :: Inclut uniquement les fichiers où l’un des Attributs donnés est défini.
    /XA:[RASHCNETO] :: eXclut les fichiers où l’un des Attributs donnés est défini.

 /XF fichier [fichier]... :: eXclut les fichiers correspondant aux noms/chemins/caractères génériques donnés.
 /XD répertoires [répertoires]... :: eXclut les répertoires correspondant à des noms/chemins donnés.

                /XC :: eXclut les fichiers Changés.
                /XN :: eXclut les fichiers Nouveaux.
                /XO :: eXclut les fichiers anciens.
                /XX :: eXclut les fichiers et répertoires supplémentaires.
                /XL :: eXclut les fichiers et répertoires solitaires.
                /IS :: Inclut les mêmeS fichiers.
                /IT :: Inclut les fichiers optimisés.

             /MAX:n :: taille de fichier maximale : exclut les fichiers de taille supérieure à n octets.
             /MIN:n :: taille de fichier minimale : exclut les fichiers de taille inférieure à n octets.

          /MAXAGE:n :: Antériorité maximale du fichier : exclut les fichiers plus anciens que n jours/qu’une date n.
          /MINAGE:n :: Antériorité minimale du fichier : exclut les fichiers plus récents que n jours/qu’une date n.
          /MAXLAD:n :: dernière date d’accès MAXimale : exclut les fichiers inutilisés depuis n.
          /MINLAD:n :: dernière date d’accès MINimale : exclut les fichiers utilisés depuis n.
                       (si n < 1900, alors n = n jours, sinon n = date JJMMAAA).

                /XJ :: eXclut les points de Jonction (normalement inclus par défaut).

               /FFT :: suppose des heures de fichier FAT (granularité de 2 secondes).
               /DST :: compense les différences d’heure d’été d’une heure.

               /XJD :: eXclut les points de Jonction pour les répertoires.
               /XJF :: eXclut les points de Jonction pour les Fichiers.

::
:: Options de nouvelle tentative :
::
               /R:n :: nombre de tentatives après l’échec de copies : 1 million par défaut.
               /W:n :: délai entre les tentatives : 30 secondes par défaut.

               /REG :: enregistre /R:n et /W:n comme paramètres par défaut dans le Registre.

               /TBD :: attend la détermination des noms de partage (erreur de nouvelle tentative 67).

::
:: Options d’enregistrement dans le journal :
::
                 /L :: Liste uniquement : pas de copie, d’horodatage ou de suppression de fichiers.
                 /X :: signale tous les fichiers supplémentaires et pas uniquement ceux sélectionnés.
                 /V :: produit un résultat détaillé en affichant les fichiers ignorés.
                /TS :: inclut les horodaTageS des fichiers sources dans le résultat.
                /FP :: inclut le chemin d’accès complet des fichiers dans le résultat.
             /BYTES :: affiche les tailles en octets.

                /NS :: pas de taille : n’enregistre pas les tailles de fichier.
                /NC :: pas de classe : n’enregistre pas les classes de fichier.
               /NFL :: pas de liste de fichiers : n’enregistre pas les noms de fichiers.
               /NDL :: pas de liste de répertoires : n’enregistre pas les noms de répertoire.

                /NP :: pas de compteur de progression : n’affiche pas le pourcentage copié.
               /ETA :: affiche l’heure de fin estimée de la copie des fichiers.

          /LOG:fichier :: copie le statut dans le fichier journal (remplace le journal existant).
         /LOG+:fichier :: copie le statut dans le fichier journal (ajoute au journal existant).

       /UNILOG:fichier :: copie le statut dans le fichier journal en Unicode (remplace le journal existant).
      /UNILOG+:fichier :: copie le statut dans le fichier journal en Unicode (ajoute au journal existant).

               /TEE :: résultat dans la fenêtre de la console et dans le fichier journal.

               /NJH :: pas d’en-tête de tâche.
               /NJS :: pas de résumé de tâche.

           /UNICODE :: sortie au format UNICODE.

::
:: Options de tâche :
::
       /JOB:NomTâche :: prend les paramètres du fichier de tâche nommé.
      /SAVE:NomTâche :: enregistre les paramètres dans le fichier nommé
              /QUIT :: arrête après traitement de la ligne de commande (pour afficher les paramètres). 
              /NOSD :: aucun répertoire source spécifié.
              /NODD :: aucun répertoire de destination spécifié.
                /IF :: Inclut les fichiers suivants.

 

Utilisation :

  • Compléter les variables suivantes dans le script :
    • $Source = "D:\Scripts\Copy-File\Stockage" (Dossier qui contient les données à copier)
    • $Destination = "D:\Scripts\Copy-File\Archivage" (Dossier de destination)

 

Screenshot :

 

Code du script :

<#
.SYNOPSIS
	Copy existing files
.DESCRIPTION
	Copy multiple files on a shared folder
.NOTES
	File name : Copy-File.ps1
	Author : Pierre JACQUOT
	Date : 13/06/2017
	Version : 1.0
.LINK
    Website : https://www.pierrejacquot.yo.fr
    Reference : https://www.pierrejacquot.yo.fr/index.php/scripts/35-script-copy-file-v1-0
#>

Clear-Host
chcp 1252 | Out-Null

$StartTime = Get-Date -Format "dd/MM/yyyy HH:mm:ss"
[string]$Hostname = [Environment]::MachineName
[string]$Login = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
[string]$Workfolder = Split-Path $MyInvocation.MyCommand.Path
[string]$Date = Get-Date -UFormat "%Y-%m-%d"
[string]$Source = "D:\Scripts\Copy-File\Stockage"
[string]$Destination = "D:\Scripts\Copy-File\Archivage"
[string]$LogFile = $Workfolder + "\$Date-Copy-File.log"
[array]$Items = Get-ChildItem -Path $Source -Recurse
[int]$ItemsNumbers = $Items.Count

Write-Host "Copy-File :" -ForegroundColor Black -BackgroundColor Yellow
Write-Host "Launching the copy of [$ItemsNumbers] item(s)." -ForegroundColor Cyan

Robocopy $Source $Destination /MIR /V /TS /FP /ETA /LOG+:$LogFile /TEE

If ($LASTEXITCODE -eq 0) {
    Write-Host "`r"
    Write-Warning "No files were copied. No failure was encountered. No files were mismatched. The files already exist in the destination directory; therefore, the copy operation was skipped."
}
ElseIf ($LASTEXITCODE -gt 8) {
    Write-Host "`r"
    Write-Host "Error during processing copy." -ForegroundColor Red
}
Else {
    Write-Host "`r"
    Write-Host "All files were copied successfully." -ForegroundColor Green
}

$EndTime = Get-Date -Format "dd/MM/yyyy HH:mm:ss"
[decimal]$Duration = [math]::Round((New-TimeSpan -Start $StartTime -End $EndTime).TotalSeconds,2)

Write-Host "`r"
Write-Host "Script launched from : " -NoNewline; Write-Host $Hostname -ForegroundColor Red
Write-Host "By : " -NoNewline; Write-Host $Login -ForegroundColor Red
Write-Host "Path : " -NoNewline; Write-Host $Workfolder -ForegroundColor Red
Write-Host "Log file : " -NoNewline; Write-Host (Split-Path $LogFile -Leaf) -ForegroundColor Red
Write-Host "Start time : " -NoNewline; Write-Host $StartTime -ForegroundColor Red
Write-Host "End time : " -NoNewline; Write-Host $EndTime -ForegroundColor Red
Write-Host "Duration : " -NoNewline; Write-Host $Duration -ForegroundColor Red -nonewline; Write-Host " seconds"
Write-Host "`r"

 

Exemple du fichier Copy-File.log créé automatiquement avec les items copiés sur l'espace de stockage :

-------------------------------------------------------------------------------
   ROBOCOPY   ::   Copie de fichiers robuste pour Windows     
-------------------------------------------------------------------------------

  Début : samedi 9 mai 2020 18:02:54
   Source : C:\Scripts\Copy-File\Stockage\
     Dest : C:\Scripts\Copy-File\Archivage\

    Fichiers : *.*
	    
  Options : *.* /V /TS /FP /TEE /S /E /DCOPY:DA /COPY:DAT /PURGE /MIR /ETA /R:1000000 /W:30 

-------------------------------------------------------------------------------

	                   0	C:\Scripts\Copy-File\Stockage\
	Nouveau rép.       1	C:\Scripts\Copy-File\Stockage\Pierre\
	  Nouveau fichier		 100.0 m 2017/06/13 20:09:52	C:\Scripts\Copy-File\Stockage\Pierre\Fichierde100Mo.txt
  0.0%
  1.0%
  2.0%
  3.0%
  4.0%
  5.0%
  6.0%
  7.0%
  8.0%
  9.0%
 10.0%
 11.0%
 12.0%
 13.0%
 14.0%
 15.0%
 16.0%
 17.0%
 18.0%
 19.0%
 20.0%
 21.0%
 22.0%
 23.0%
 24.0%
 25.0%
 26.0%
 27.0%
 28.0%
 29.0%
 30.0%
 31.0%
 32.0%
 33.0%
 34.0%
 35.0%
 36.0%
 37.0%
 38.0%
 39.0%
 40.0%
 41.0%
 42.0%
 43.0%
 44.0%
 45.0%
 46.0%
 47.0%
 48.0%
 49.0%
 50.0%
 51.0%
 52.0%
 53.0%
 54.0%
 55.0%
 56.0%
 57.0%
 58.0%
 59.0%
 60.0%
 61.0%
 62.0%
 63.0%
 64.0%
 65.0%
 66.0%
 67.0%
 68.0%
 69.0%
 70.0%
 71.0%
 72.0%
 73.0%
 74.0%
 75.0%
 76.0%
 77.0%
 78.0%
 79.0%
 80.0%
 81.0%
 82.0%
 83.0%
 84.0%
 85.0%
 86.0%
 87.0%
 88.0%
 89.0%
 90.0%
 91.0%
 92.0%
 93.0%
 94.0%
 95.0%
 96.0%
 97.0%
 98.0%
 99.0%
100%  

-------------------------------------------------------------------------------

               Total     Copié    IgnoréDiscordance     ÉCHEC    Extras
     Rép :         2         1         1         0         0         0
Fichiers :         1         1         0         0         0         0
  Octets :  100.00 m  100.00 m         0         0         0         0
   Heures:   0:00:01   0:00:01                       0:00:00   0:00:00


   Débit :            74525657 Octets/sec.
   Débit :            4264.392 Méga-octets/min.
   Fin : samedi 9 mai 2020 18:02:56

 

Cliquer ici pour télécharger le script.

 

Ce script créé par mes soins permet de zipper des dossiers (informations stockées dans un fichier csv) en masse sur un espace de stockage avec la création d'un fichier qui log les actions effectuées.

 

Fonctionnalités :

  • Créer des archives au format zip (stockés dans un fichier csv) sur un espace de stockage
  • Création d'un fichier de logs horodatés (Create-Zip)
  • Exporter les données dans un fichier .csv
  • Exporter les données dans un rapport HTML

 

Pour des raisons de compatibilité, j'utilise dans ce script l'API System.IO.Compression.FileSystem.

 

Il est également possible d'utiliser la cmdlet Compress-Archive (PowerShell 5+) qui repose sur l'API System.IO.Compression.ZipArchive et qui affiche une barre de progression lors de la compression d'un fichier.

 

Par contre, la taille maximale d'un fichier que vous pouvez compresser en utilisant Compress-Archive est limitée à 2 Go.

 

Pour rappel, le taux de compression d'un fichier de log est de 100%.

 

Exemples :

  • Après compression d'un fichier de log d'une taille de 1 Go, celui-ci pèse 1 Mo
  • Après compression d'un fichier de log d'une taille de 2 Go, celui-ci pèse 2 Mo

 

Utilisation :

  • Compléter le fichier Zip-Records.csv avec les archives zip à créer automatiquement

 

Exemple du fichier Zip-Records.csv avec les informations des dossiers à zipper :

User;SourceFolder;DestinationZip
Pierre;D:\Scripts\Create-Zip\Stockage\;D:\Scripts\Create-Zip\
Thomas;D:\Scripts\Create-Zip\Stockage\;D:\Scripts\Create-Zip\

 

Screenshot :

 

Code du script :

<#
.SYNOPSIS
    Zip files creation
.DESCRIPTION
    Create multiple zip files on a shared folder
.NOTES
    File name : Create-Zip.ps1
    Author : Pierre JACQUOT
    Date : 08/06/2017
    Version : 1.0
.LINK
    Website : https://www.pierrejacquot.yo.fr
    Reference : https://www.pierrejacquot.yo.fr/index.php/scripts/34-script-create-zip
#>

Clear-Host

Function Write-Log([string]$Output, [string]$Message) {
    Write-Verbose $Message
    ((Get-Date -UFormat "[%d/%m/%Y %H:%M:%S] ") + $Message) | Out-File -FilePath $Output -Append -Force
}

$StartTime = Get-Date -Format "dd/MM/yyyy HH:mm:ss"
[string]$Hostname = [Environment]::MachineName
[string]$Login = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
[string]$Workfolder = Split-Path $MyInvocation.MyCommand.Path
[string]$Date = Get-Date -UFormat "%Y-%m-%d"
[string]$CSVFile = $Workfolder + "\Zip-Records.csv"
[string]$ReportFile = $Workfolder + "\$Date-ZipRecords-Report.html"
[string]$LogFile = $Workfolder + "\$Date-Create-Zip.log"
Write-Host "Create-Zip :" -ForegroundColor Black -BackgroundColor Yellow
Try {
    [array]$Records = Import-Csv -Path ".\Zip-Records.csv" -Delimiter ";" -Encoding UTF8
}
Catch {
    [string]$ErrorMessage = $_.Exception.Message
    Write-Host $ErrorMessage -ForegroundColor Red
    Write-Log -Output $LogFile -Message $ErrorMessage
}
$Records | Add-Member -Type NoteProperty -Name "ZipFile" -Value "N/A"
$Records | Add-Member -Type NoteProperty -Name "ZipContent" -Value "N/A"
$Records | Add-Member -Type NoteProperty -Name "Status" -Value "N/A"
[int]$LineNumbers = $Records.Count
[string]$Activity = "Trying to launch the creation of [$LineNumbers] zip file(s)"
[int]$Step = 1
[string]$Title = "[$Date] - Zip file(s) creation report on : $Hostname"

If ((Test-Path ".\Zip-Records.csv") -eq $True -and $LineNumbers -eq 0) {
    Write-Warning "CSV file [Zip-Records.csv] is empty."
    Write-Log -Output $LogFile -Message "CSV file [Zip-Records.csv] is empty."
}
ElseIf ($LineNumbers -ge 1) {
    Write-Host "Launching the creation of [$LineNumbers] zip file(s)." -ForegroundColor Cyan
    Write-Host "`r"
    ForEach ($Record in $Records) {
        [string]$User = $Record.User
        [string]$SourceFolder = $Record.SourceFolder+"$User\"
        [string]$DestinationZip = $Record.DestinationZip+"$Date-Archive-$User.zip"
        [string]$Status = "Processing [$Step] of [$LineNumbers] - $(([math]::Round((($Step)/$LineNumbers*100),0)))% completed"
        [string]$CurrentOperation = "Creating zip file : $DestinationZip"
        Write-Progress -Activity $Activity -Status $Status -CurrentOperation $CurrentOperation -PercentComplete ($Step/$LineNumbers*100)
        $Step++
        Start-Sleep -Seconds 1
        Try {
            $Record.Status = "OK"
            If ((Test-Path $DestinationZip) -eq $True) {
                Remove-Item $DestinationZip
                Write-Host "The file $DestinationZip has been removed." -ForegroundColor Green
                Write-Log -Output $LogFile -Message "The file $DestinationZip has been removed."
            }
            Add-Type -Assembly "System.IO.Compression.FileSystem"
            [IO.Compression.ZipFile]::CreateFromDirectory($SourceFolder, $DestinationZip)
            Write-Host "The file $DestinationZip has been created." -ForegroundColor Green
            Write-Log -Output $LogFile -Message "The file $DestinationZip has been created."
            $Record.ZipFile = (Split-Path $DestinationZip -Leaf)
            $Record.ZipContent = [System.IO.Compression.ZipFile]::OpenRead($DestinationZip).Entries.Name -join ", "
        }
        Catch {
            $Record.Status = "KO"
            [string]$ErrorMessage = $_.Exception.Message
            Write-Host $ErrorMessage -ForegroundColor Red
            Write-Log -Output $LogFile -Message $ErrorMessage
        }
    }
}

$EndTime = Get-Date -Format "dd/MM/yyyy HH:mm:ss"
[decimal]$Duration = [math]::Round((New-TimeSpan -Start $StartTime -End $EndTime).TotalSeconds,2)
[string]$PreContent = "<h1>$Title</h1>
<h2>Number of Zip file(s) : <span class='PostContentBlue'>$LineNumbers</span></h2>"
[string]$PostContent = "<p id='PostContent'>Script launched from : <span class='PostContentBlue'>$Hostname</span><br/>
By : <span class='PostContentBlue'>$Login</span><br/>
Path : <span class='PostContentBlue'>$Workfolder</span><br/>
CSV file : <span class='PostContentBlue'>$(Split-Path $CSVFile -Leaf)</span><br/>
Report file : <span class='PostContentBlue'>$(Split-Path $ReportFile -Leaf)</span><br/>
Log file : <span class='PostContentBlue'>$(Split-Path $LogFile -Leaf)</span><br/>
Start time : <span class='PostContentBlue'>$StartTime</span><br/>
End time : <span class='PostContentBlue'>$EndTime</span><br/>
Duration : <span class='PostContentBlue'>$Duration</span> second(s)</p>"
[string]$Report = $Records | ConvertTo-Html -As Table -CssUri ".\Style.css" -Title $Title -PreContent $PreContent -PostContent $PostContent
$Report = $Report -replace '<td>OK</td>','<td class="SuccessStatus">OK</td>'
$Report = $Report -replace '<td>KO</td>','<td class="CriticalStatus">KO</td>'
$Report | Out-File -FilePath $ReportFile -Encoding utf8

Write-Host "`r"
Write-Host "Script launched from : " -NoNewline; Write-Host $Hostname -ForegroundColor Red
Write-Host "By : " -NoNewline; Write-Host $Login -ForegroundColor Red
Write-Host "Path : " -NoNewline; Write-Host $Workfolder -ForegroundColor Red
Write-Host "CSV file : " -NoNewline; Write-Host (Split-Path $CSVFile -Leaf) -ForegroundColor Red
Write-Host "Report file : " -NoNewline; Write-Host (Split-Path $ReportFile -Leaf) -ForegroundColor Red
Write-Host "Log file : " -NoNewline; Write-Host (Split-Path $LogFile -Leaf) -ForegroundColor Red
Write-Host "Start time : " -NoNewline; Write-Host $StartTime -ForegroundColor Red
Write-Host "End time : " -NoNewline; Write-Host $EndTime -ForegroundColor Red
Write-Host "Duration : " -NoNewline; Write-Host $Duration -ForegroundColor Red -nonewline; Write-Host " second(s)"
Write-Host "`r"

 

Exemple du fichier Create-Zip.log créé automatiquement avec les fichiers zip créés sur l'espace de stockage :

[09/05/2020 17:51:24] The file C:\Scripts\Create-Zip\Zip\2020-05-09-Archive-Pierre.zip has been created.
[09/05/2020 17:51:51] The file C:\Scripts\Create-Zip\Zip\2020-05-09-Archive-Thomas.zip has been created.

 

Cliquer ici pour visualiser un exemple du rapport ZipRecords-Report.html créé automatiquement depuis mon poste.

 

Cliquer ici pour télécharger le fichier de style css.

 

Cliquer ici pour télécharger le script.

 

One-Liner :

#OL01 - Créer un fichier d’une taille définie (1 Go en octets)

fsutil file createnew C:\Temp\Fichierde1Go.txt 1073741824

 

Ce script créé par mes soins permet de créer des enregistrements DNS avec PTR (informations stockées dans un fichier csv) en masse sur le serveur DNS avec la création d'un fichier qui log les actions effectuées.

 

Fonctionnalités :

  • Créer des enregistrements DNS avec leurs PTR associés (stockés dans un fichier csv) sur le serveur DNS
  • Création d'un fichier de logs horodatés (Add-DNS)
  • Exporter les données dans un fichier .csv
  • Exporter les données dans un rapport HTML

 

Ici nous utilisons pour des raisons de compatibilité la cmdlet DNSCMD afin d’effectuer les modifications. Sur Windows Server 2012 de nouvelles cmdlet existent afin de communiquer avec le service DNS.

 

Utilisation :

  • Compléter le fichier DNS-Records.csv avec les enregistrements à créer automatiquement

 

Exemple du fichier DNS-Records.csv avec les informations des enregistrements DNS de type [A] :

DNSName;DNSType;DNSIP;DNSZone;DNSServer
DNSNAME01;A;192.168.100.3;lab.microsoft.com;SRVDC01
DNSNAME02;A;192.168.100.4;lab.microsoft.com;SRVDC01
DNSNAME03;A;192.168.100.5;lab.microsoft.com;SRVDC01

 

Screenshot :

 

Code du script :

<#
.SYNOPSIS
    DNS records creation
.DESCRIPTION
    Create multiple DNS records with associated PTR
.NOTES
    File name : Add-DNS.ps1
    Author : Pierre JACQUOT
    Date : 07/05/2017
    Version : 1.0
.LINK
    Website : https://www.pierrejacquot.yo.fr
    Reference : https://www.pierrejacquot.yo.fr/index.php/scripts/31-script-add-dns-v1-0
#>

Clear-Host

Function Write-Log([string]$Output, [string]$Message) {
    Write-Verbose $Message
    ((Get-Date -UFormat "[%d/%m/%Y %H:%M:%S] ") + $Message) | Out-File -FilePath $Output -Append -Force
}

$StartTime = Get-Date -Format "dd/MM/yyyy HH:mm:ss"
[string]$Hostname = [Environment]::MachineName
[string]$Login = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
[string]$Workfolder = Split-Path $MyInvocation.MyCommand.Path
[string]$Date = Get-Date -UFormat "%Y-%m-%d"
[string]$CSVFile = $Workfolder + "\DNS-Records.csv"
[string]$ReportFile = $Workfolder + "\$Date-DNSRecords-Report.html"
[string]$LogFile = $Workfolder + "\$Date-Add-DNS.log"
Write-Host "Add-DNS :" -ForegroundColor Black -BackgroundColor Yellow
Try {
    [array]$Records = Import-Csv -Path ".\DNS-Records.csv" -Delimiter ";" -Encoding UTF8
}
Catch {
    [string]$ErrorMessage = $_.Exception.Message
    Write-Host $ErrorMessage -ForegroundColor Red
    Write-Log -Output $LogFile -Message $ErrorMessage
}
$Records | Add-Member -Type NoteProperty -Name "Status" -Value "N/A"
[int]$LineNumbers = $Records.Count
[string]$Activity = "Trying to launch the creation of [$LineNumbers] DNS record(s)"
[int]$Step = 1
[string]$Title = "[$Date] - DNS record(s) creation report on : $Hostname"

If ((Test-Path ".\DNS-Records.csv") -eq $True -and $LineNumbers -eq 0) {
    Write-Warning "CSV file [DNS-Records.csv] is empty."
    Write-Log -Output $LogFile -Message "CSV file [DNS-Records.csv] is empty."
}
ElseIf ($LineNumbers -ge 1) {
    Write-Host "Launching the creation of [$LineNumbers] DNS record(s)." -ForegroundColor Cyan
    Write-Host "`r"
    ForEach ($Record in $Records) {
        [string]$RecordName = $Record.DNSName
        [string]$RecordType = $Record.DNSType
        [string]$RecordIP = $Record.DNSIP
        [string]$RecordZone = $Record.DNSZone
        [string]$RecordServer = $Record.DNSServer
        [string]$Status = "Processing [$Step] of [$LineNumbers] - $(([math]::Round((($Step)/$LineNumbers*100),0)))% completed"
        [string]$CurrentOperation = "Adding DNS record : Name $RecordName - Type : $RecordType - IP : $RecordIP - Zone : $RecordZone - DNS Server : $RecordServer"
        Write-Progress -Activity $Activity -Status $Status -CurrentOperation $CurrentOperation -PercentComplete ($Step/$LineNumbers*100)
        $Step++
        Start-Sleep -Seconds 1
        Try {
            $Record.Status = "OK"
            [string]$cmdDelete = "DNSCmd $RecordServer /RecordDelete $RecordZone $RecordName $RecordType $RecordIP /f"
            Write-Host "[DELETE] - Running this command : $cmdDelete" -ForegroundColor Yellow
            Invoke-Expression $cmdDelete | Out-Null
            Write-Host "`t[$RecordName - $RecordType - $RecordIP - $RecordZone] has been deleted." -ForegroundColor Green
            Write-Log -Output $LogFile -Message "[$RecordName - $RecordType - $RecordIP - $RecordZone] has been deleted."
            Write-Host "`r"

            [string]$cmdAdd = "DNSCmd $RecordServer /RecordAdd $RecordZone $RecordName /CreatePTR $RecordType $RecordIP"
            Invoke-Expression $cmdAdd | Out-Null
            Write-Host "[ADD] - Running this command : $cmdAdd" -ForegroundColor Cyan
            Write-Host "`t[$RecordName - $RecordType - $RecordIP - $RecordZone] has been added." -ForegroundColor Green
            Write-Log -Output $LogFile -Message "[$RecordName - $RecordType - $RecordIP - $RecordZone] has been added."
            Write-Host "`r"
        }
        Catch {
            $Record.Status = "KO"
            [string]$ErrorMessage = $_.Exception.Message
            Write-Host $ErrorMessage -ForegroundColor Red
            Write-Log -Output $LogFile -Message $ErrorMessage
            Write-Host "`r"
        }
    }
}

$EndTime = Get-Date -Format "dd/MM/yyyy HH:mm:ss"
[decimal]$Duration = [math]::Round((New-TimeSpan -Start $StartTime -End $EndTime).TotalSeconds,2)
[string]$PreContent = "<h1>$Title</h1>
<h2>Number of DNS record(s) : <span class='PostContentBlue'>$LineNumbers</span></h2>"
[string]$PostContent = "<p id='PostContent'>Script launched from : <span class='PostContentBlue'>$Hostname</span><br/>
By : <span class='PostContentBlue'>$Login</span><br/>
Path : <span class='PostContentBlue'>$Workfolder</span><br/>
CSV file : <span class='PostContentBlue'>$(Split-Path $CSVFile -Leaf)</span><br/>
Report file : <span class='PostContentBlue'>$(Split-Path $ReportFile -Leaf)</span><br/>
Log file : <span class='PostContentBlue'>$(Split-Path $LogFile -Leaf)</span><br/>
Start time : <span class='PostContentBlue'>$StartTime</span><br/>
End time : <span class='PostContentBlue'>$EndTime</span><br/>
Duration : <span class='PostContentBlue'>$Duration</span> second(s)</p>"
[string]$Report = $Records | ConvertTo-Html -As Table -CssUri ".\Style.css" -Title $Title -PreContent $PreContent -PostContent $PostContent
$Report = $Report -replace '<td>OK</td>','<td class="SuccessStatus">OK</td>'
$Report = $Report -replace '<td>KO</td>','<td class="CriticalStatus">KO</td>'
$Report | Out-File -FilePath $ReportFile -Encoding utf8

Write-Host "`r"
Write-Host "Script launched from : " -NoNewline; Write-Host $Hostname -ForegroundColor Red
Write-Host "By : " -NoNewline; Write-Host $Login -ForegroundColor Red
Write-Host "Path : " -NoNewline; Write-Host $Workfolder -ForegroundColor Red
Write-Host "CSV file : " -NoNewline; Write-Host (Split-Path $CSVFile -Leaf) -ForegroundColor Red
Write-Host "Report file : " -NoNewline; Write-Host (Split-Path $ReportFile -Leaf) -ForegroundColor Red
Write-Host "Log file : " -NoNewline; Write-Host (Split-Path $LogFile -Leaf) -ForegroundColor Red
Write-Host "Start time : " -NoNewline; Write-Host $StartTime -ForegroundColor Red
Write-Host "End time : " -NoNewline; Write-Host $EndTime -ForegroundColor Red
Write-Host "Duration : " -NoNewline; Write-Host $Duration -ForegroundColor Red -nonewline; Write-Host " second(s)"
Write-Host "`r"

 

Exemple du fichier Add-DNS.log créé automatiquement avec les enregistrements DNS créés sur le serveur DNS :

[09/05/2020 17:07:53] [DNSNAME01 - A - 192.168.100.3 - lab.microsoft.com] has been deleted.
[09/05/2020 17:07:53] [DNSNAME01 - A - 192.168.100.3 - lab.microsoft.com] has been added.
[09/05/2020 17:07:55] [DNSNAME02 - A - 192.168.100.4 - lab.microsoft.com] has been deleted.
[09/05/2020 17:07:55] [DNSNAME02 - A - 192.168.100.4 - lab.microsoft.com] has been added.
[09/05/2020 17:07:56] [DNSNAME03 - A - 192.168.100.5 - lab.microsoft.com] has been deleted.
[09/05/2020 17:07:56] [DNSNAME03 - A - 192.168.100.5 - lab.microsoft.com] has been added.

 

Cliquer ici pour visualiser un exemple du rapport Folders-Report.html créé automatiquement.

 

Cliquer ici pour télécharger le fichier de style css.

 

Cliquer ici pour télécharger le script.

 

One-Liners :

#OL01 - Créer des enregistrements DNS de type [A] avec leurs PTR associés (stockés dans un fichier csv) sur le serveur DNS

Import-CSV -Path "C:\Temp\DNS-A-Records.csv" -Delimiter ";" | ForEach-Object { DNSCmd.exe $_.DNSServer /RecordAdd $_.DNSZone $_.DNSName /CreatePTR $_.DNSType $_.DNSIP }

 

Exemple du fichier DNS-A-Records.csv avec les informations des enregistrements DNS de type [A] :

DNSName;DNSType;DNSIP;DNSZone;DNSServer
DNSNAME01;A;192.168.100.3;lab.microsoft.com;SRVDC01
DNSNAME02;A;192.168.100.4;lab.microsoft.com;SRVDC01
DNSNAME03;A;192.168.100.5;lab.microsoft.com;SRVDC01

 

#OL02 - Supprimer des enregistrements DNS de type [A] avec leurs PTR associés (stockés dans un fichier csv) sur le serveur DNS

Import-CSV -Path "C:\Temp\DNS-A-Records.csv" -Delimiter ";" | ForEach-Object { DNSCmd.exe $_.DNSServer /RecordDelete $_.DNSZone $_.DNSName $_.DNSType $_.DNSIP /f }

 

#OL03 - Créer des enregistrements DNS de type [CNAME] (stockés dans un fichier csv) sur le serveur DNS

Import-CSV -Path "C:\Temp\DNS-CNAME-Records.csv" -Delimiter ";" | ForEach-Object { DNSCmd.exe $_.DNSServer /RecordAdd $_.DNSZone $_.DNSAliasName CNAME $_.DNSFQDNName }

 

Exemple du fichier DNS-CNAME-Records.csv avec les informations des enregistrements DNS de type [CNAME] :

DNSAliasName;DNSFQDNName;DNSZone;DNSServer
DNSALIASNAME01;HOSTNAME.lab.microsoft.com;lab.microsoft.com;SRVDC01
DNSALIASNAME02;HOSTNAME.lab.microsoft.com;lab.microsoft.com;SRVDC01
DNSALIASNAME03;HOSTNAME.lab.microsoft.com;lab.microsoft.com;SRVDC01

 

#OL04 - Supprimer des enregistrements DNS de type [CNAME] (stockés dans un fichier csv) sur le serveur DNS

Import-CSV -Path "C:\Temp\DNS-CNAME-Records.csv" -Delimiter ";" | ForEach-Object { DNSCmd.exe $_.DNSServer /RecordDelete $_.DNSZone $_.DNSAliasName CNAME $_.DNSFQDNName /f }

 

Ce script créé par mes soins permet de supprimer des utilisateurs (informations stockées dans un fichier csv) en masse d'un ou de plusieurs groupes AD avec la création d'un fichier qui log les actions effectuées.

 

Fonctionnalités :

  • Supprime des utilisateurs (informations stockées dans un fichier csv) en masse d'un ou de plusieurs groupes AD
  • Création d'un fichier de logs horodatés (Remove-User)
  • Exporter les données dans un fichier .csv
  • Exporter les données dans un rapport HTML

 

Prérequis :

 

Utilisation :

  • Compléter le fichier Remove-User.csv avec les logins et les noms des groupes AD

 

Exemple du fichier Remove-User.csv avec les logins et les noms des groupes AD :

SamAccountName;GroupName
Administrateur;C_Helpdesk-JoinAD
Invité;IT_Systeme
Pierre;DSI_RW

 

Screenshot :

 

Code du script :

<#
.SYNOPSIS
    Remove AD users
.DESCRIPTION
    Remove multiple users in AD group(s)
.NOTES
    File name : Remove-User.ps1
    Author : Pierre JACQUOT
    Date : 16/05/2016
    Version : 1.0
.LINK
    Website : https://www.pierrejacquot.yo.fr
    Reference : https://www.pierrejacquot.yo.fr/index.php/scripts/28-script-remove-user
#>

Clear-Host

Function Write-Log([string]$Output, [string]$Message) {
    Write-Verbose $Message
    ((Get-Date -UFormat "[%d/%m/%Y %H:%M:%S] ") + $Message) | Out-File -FilePath $Output -Append -Force
}

$StartTime = Get-Date -Format "dd/MM/yyyy HH:mm:ss"
[string]$Hostname = [Environment]::MachineName
[string]$Login = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
[string]$Workfolder = Split-Path $MyInvocation.MyCommand.Path
[string]$Date = Get-Date -UFormat "%Y-%m-%d"
[string]$CSVFile = $Workfolder + "\Remove-User.csv"
[string]$ReportFile = $Workfolder + "\$Date-UsersRemoval-Report.html"
[string]$LogFile = $Workfolder + "\$Date-Remove_User.log"

Write-Host "Remove-User :" -ForegroundColor Black -BackgroundColor Yellow
Try {
    Import-Module ActiveDirectory -ErrorAction Stop
    Write-Host "ActiveDirectory module has been imported." -ForegroundColor Green
    Write-Log -Output $LogFile -Message "ActiveDirectory module has been imported."
}
Catch {
    Write-Warning "The ActiveDirectory module failed to load. Install the module and try again."
    Write-Log -Output $LogFile -Message "The ActiveDirectory module failed to load. Install the module and try again."
    Pause
    Write-Host "`r"
    Exit
}
Try {
    [array]$Records = Import-Csv -Path ".\Remove-User.csv" -Delimiter ";" -Encoding UTF8
}
Catch {
    [string]$ErrorMessage = $_.Exception.Message
    Write-Host $ErrorMessage -ForegroundColor Red
    Write-Log -Output $LogFile -Message $ErrorMessage
}
$Records | Add-Member -Type NoteProperty -Name "Status" -Value "N/A"
[int]$LineNumbers = $Records.Count
[string]$Activity = "Trying to launch the deletion of [$LineNumbers] user(s) into AD group(s)"
[int]$Step = 1
[string]$Title = "[$Date] - AD user(s) removal report on : $Hostname"

If ((Test-Path ".\Remove-User.csv") -eq $True -and $LineNumbers -eq 0) {
    Write-Warning "CSV file [Remove-User.csv] is empty."
    Write-Log -Output $LogFile -Message "CSV file [Remove-User.csv] is empty."
}
ElseIf ($LineNumbers -ge 1) {
    Write-Host "Launching the deletion of [$LineNumbers] user(s) from an AD group." -ForegroundColor Cyan
    Write-Host "`r"
    ForEach ($Record in $Records) {
        [string]$LoginName = $Record.sAMAccountName
        [string]$GroupName = $Record.GroupName
        [string]$Status = "Processing [$Step] of [$LineNumbers] - $(([math]::Round((($Step)/$LineNumbers*100),0)))% completed"
        [string]$CurrentOperation = "Removing AD user : $LoginName into the group : $GroupName"
        Write-Progress -Activity $Activity -Status $Status -CurrentOperation $CurrentOperation -PercentComplete ($Step/$LineNumbers*100)
        $Step++
        Start-Sleep -Seconds 1
        Try {
            $Record.Status = "OK"
            Remove-ADGroupMember -Identity $GroupName -Members $LoginName -Confirm:$false
            Write-Host "$LoginName has been removed of the group : $GroupName." -ForegroundColor Green
            Write-Log -Output $LogFile -Message "$LoginName has been removed of the group : $GroupName."
        }
        Catch {
            $Record.Status = "KO"
            [string]$ErrorMessage = $_.Exception.Message
            Write-Host $ErrorMessage -ForegroundColor Red
            Write-Log -Output $LogFile -Message $ErrorMessage
            Write-Host "`r"
        }
    }
}

$EndTime = Get-Date -Format "dd/MM/yyyy HH:mm:ss"
[decimal]$Duration = [math]::Round((New-TimeSpan -Start $StartTime -End $EndTime).TotalSeconds,2)
[string]$PreContent = "<h1>$Title</h1>
<h2>Number of AD user(s) : <span class='PostContentBlue'>$LineNumbers</span></h2>"
[string]$PostContent = "<p id='PostContent'>Script launched from : <span class='PostContentBlue'>$Hostname</span><br/>
By : <span class='PostContentBlue'>$Login</span><br/>
Path : <span class='PostContentBlue'>$Workfolder</span><br/>
CSV file : <span class='PostContentBlue'>$(Split-Path $CSVFile -Leaf)</span><br/>
Report file : <span class='PostContentBlue'>$(Split-Path $ReportFile -Leaf)</span><br/>
Log file : <span class='PostContentBlue'>$(Split-Path $LogFile -Leaf)</span><br/>
Start time : <span class='PostContentBlue'>$StartTime</span><br/>
End time : <span class='PostContentBlue'>$EndTime</span><br/>
Duration : <span class='PostContentBlue'>$Duration</span> second(s)</p>"
[string]$Report = $Records | ConvertTo-Html -As Table -CssUri ".\Style.css" -Title $Title -PreContent $PreContent -PostContent $PostContent
$Report = $Report -replace '<td>OK</td>','<td class="SuccessStatus">OK</td>'
$Report = $Report -replace '<td>KO</td>','<td class="CriticalStatus">KO</td>'
$Report | Out-File -FilePath $ReportFile -Encoding utf8

Write-Host "`r"
Write-Host "Script launched from : " -NoNewline; Write-Host $Hostname -ForegroundColor Red
Write-Host "By : " -NoNewline; Write-Host $Login -ForegroundColor Red
Write-Host "Path : " -NoNewline; Write-Host $Workfolder -ForegroundColor Red
Write-Host "CSV file : " -NoNewline; Write-Host (Split-Path $CSVFile -Leaf) -ForegroundColor Red
Write-Host "Report file : " -NoNewline; Write-Host (Split-Path $ReportFile -Leaf) -ForegroundColor Red
Write-Host "Log file : " -NoNewline; Write-Host (Split-Path $LogFile -Leaf) -ForegroundColor Red
Write-Host "Start time : " -NoNewline; Write-Host $StartTime -ForegroundColor Red
Write-Host "End time : " -NoNewline; Write-Host $EndTime -ForegroundColor Red
Write-Host "Duration : " -NoNewline; Write-Host $Duration -ForegroundColor Red -nonewline; Write-Host " second(s)"
Write-Host "`r"

 

Exemple du fichier Remove-User.log créé automatiquement avec les logins des utilisateurs supprimés du groupe AD :

[09/05/2020 16:29:05] ActiveDirectory module has been imported.
[09/05/2020 16:29:06] Administrateur has been removed of the group : C_Helpdesk-JoinAD.
[09/05/2020 16:29:07] Invité has been removed of the group : IT_Systeme.
[09/05/2020 16:29:08] Pierre has been removed of the group : DSI_RW.

 

Cliquer ici pour visualiser un exemple du rapport UsersRemoval-Report.html créé automatiquement depuis mon poste.

 

Cliquer ici pour télécharger le fichier de style css.

 

Cliquer ici pour télécharger le script.

 

Ce script créé par mes soins permet d'ajouter des utilisateurs (informations stockées dans un fichier texte) en masse dans un ou plusieurs groupes AD avec la création d'un fichier qui log les actions effectuées.

 

Fonctionnalités :

  • Ajoute des utilisateurs (informations stockées dans un fichier texte) en masse dans un ou plusieurs groupes AD
  • Création d'un fichier de logs horodatés (Add-User)
  • Exporter les données dans un fichier .csv
  • Exporter les données dans un rapport HTML

 

Prérequis :

 

Utilisation :

  • Compléter le fichier Add-User.csv avec les logins et les noms des groupes AD

 

Exemple du fichier Add-User.csv avec les logins et les noms des groupes AD :

SamAccountName;GroupName
Administrateur;C_Helpdesk-JoinAD
Invité;IT_Systeme
Pierre;DSI_RW

 

Screenshot :

 

Code du script :

<#
.SYNOPSIS
    Add AD users
.DESCRIPTION
    Add multiple users in AD group(s)
.NOTES
    File name : Add-User.ps1
    Author : Pierre JACQUOT
    Date : 16/05/2016
    Version : 1.0
.LINK
    Website : https://www.pierrejacquot.yo.fr
    Reference : https://www.pierrejacquot.yo.fr/index.php/scripts/27-script-add-user
#>

Clear-Host

Function Write-Log([string]$Output, [string]$Message) {
    Write-Verbose $Message
    ((Get-Date -UFormat "[%d/%m/%Y %H:%M:%S] ") + $Message) | Out-File -FilePath $Output -Append -Force
}

$StartTime = Get-Date -Format "dd/MM/yyyy HH:mm:ss"
[string]$Hostname = [Environment]::MachineName
[string]$Login = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
[string]$Workfolder = Split-Path $MyInvocation.MyCommand.Path
[string]$Date = Get-Date -UFormat "%Y-%m-%d"
[string]$CSVFile = $Workfolder + "\Add-User.csv"
[string]$ReportFile = $Workfolder + "\$Date-Users-Report.html"
[string]$LogFile = $Workfolder + "\$Date-Add-User.log"

Write-Host "Add-User :" -ForegroundColor Black -BackgroundColor Yellow
Try {
    Import-Module ActiveDirectory -ErrorAction Stop
    Write-Host "ActiveDirectory module has been imported." -ForegroundColor Green
    Write-Log -Output $LogFile -Message "ActiveDirectory module has been imported."
}
Catch {
    Write-Warning "The ActiveDirectory module failed to load. Install the module and try again."
    Write-Log -Output $LogFile -Message "The ActiveDirectory module failed to load. Install the module and try again."
    Pause
    Write-Host "`r"
    Exit
}
Try {
    [array]$Records = Import-Csv -Path ".\Add-User.csv" -Delimiter ";" -Encoding UTF8
}
Catch {
    [string]$ErrorMessage = $_.Exception.Message
    Write-Host $ErrorMessage -ForegroundColor Red
    Write-Log -Output $LogFile -Message $ErrorMessage
}
$Records | Add-Member -Type NoteProperty -Name "Status" -Value "N/A"
[int]$LineNumbers = $Records.Count
[string]$Activity = "Trying to launch the addition of [$LineNumbers] user(s) into AD group(s)"
[int]$Step = 1
[string]$Title = "[$Date] - AD user(s) addition report on : $Hostname"

If ((Test-Path ".\Add-User.csv") -eq $True -and $LineNumbers -eq 0) {
    Write-Warning "CSV file [Add-User.csv] is empty."
    Write-Log -Output $LogFile -Message "CSV file [Add-User.csv] is empty."
}
ElseIf ($LineNumbers -ge 1) {
    Write-Host "Launching the addition of [$LineNumbers] user(s) into AD group(s)." -ForegroundColor Cyan
    Write-Host "`r"
    ForEach ($Record in $Records) {
        [string]$LoginName = $Record.sAMAccountName
        [string]$GroupName = $Record.GroupName
        [string]$Status = "Processing [$Step] of [$LineNumbers] - $(([math]::Round((($Step)/$LineNumbers*100),0)))% completed"
        [string]$CurrentOperation = "Adding AD user : $LoginName into the group : $GroupName"
        Write-Progress -Activity $Activity -Status $Status -CurrentOperation $CurrentOperation -PercentComplete ($Step/$LineNumbers*100)
        $Step++
        Start-Sleep -Seconds 1
        Try {
            $Record.Status = "OK"
            Add-ADGroupMember -Identity $GroupName -Members $LoginName
            Write-Host "$LoginName has been added into the group : $GroupName." -ForegroundColor Green
            Write-Log -Output $LogFile -Message "$LoginName has been added into the group : $GroupName."
        }
        Catch {
            $Record.Status = "KO"
            [string]$ErrorMessage = $_.Exception.Message
            Write-Host $ErrorMessage -ForegroundColor Red
            Write-Log -Output $LogFile -Message $ErrorMessage
            Write-Host "`r"
        }
    }
}

$EndTime = Get-Date -Format "dd/MM/yyyy HH:mm:ss"
[decimal]$Duration = [math]::Round((New-TimeSpan -Start $StartTime -End $EndTime).TotalSeconds,2)
[string]$PreContent = "<h1>$Title</h1>
<h2>Number of AD user(s) : <span class='PostContentBlue'>$LineNumbers</span></h2>"
[string]$PostContent = "<p id='PostContent'>Script launched from : <span class='PostContentBlue'>$Hostname</span><br/>
By : <span class='PostContentBlue'>$Login</span><br/>
Path : <span class='PostContentBlue'>$Workfolder</span><br/>
CSV file : <span class='PostContentBlue'>$(Split-Path $CSVFile -Leaf)</span><br/>
Report file : <span class='PostContentBlue'>$(Split-Path $ReportFile -Leaf)</span><br/>
Log file : <span class='PostContentBlue'>$(Split-Path $LogFile -Leaf)</span><br/>
Start time : <span class='PostContentBlue'>$StartTime</span><br/>
End time : <span class='PostContentBlue'>$EndTime</span><br/>
Duration : <span class='PostContentBlue'>$Duration</span> second(s)</p>"
[string]$Report = $Records | ConvertTo-Html -As Table -CssUri ".\Style.css" -Title $Title -PreContent $PreContent -PostContent $PostContent
$Report = $Report -replace '<td>OK</td>','<td class="SuccessStatus">OK</td>'
$Report = $Report -replace '<td>KO</td>','<td class="CriticalStatus">KO</td>'
$Report | Out-File -FilePath $ReportFile -Encoding utf8

Write-Host "`r"
Write-Host "Script launched from : " -NoNewline; Write-Host $Hostname -ForegroundColor Red
Write-Host "By : " -NoNewline; Write-Host $Login -ForegroundColor Red
Write-Host "Path : " -NoNewline; Write-Host $Workfolder -ForegroundColor Red
Write-Host "CSV file : " -NoNewline; Write-Host (Split-Path $CSVFile -Leaf) -ForegroundColor Red
Write-Host "Report file : " -NoNewline; Write-Host (Split-Path $ReportFile -Leaf) -ForegroundColor Red
Write-Host "Log file : " -NoNewline; Write-Host (Split-Path $LogFile -Leaf) -ForegroundColor Red
Write-Host "Start time : " -NoNewline; Write-Host $StartTime -ForegroundColor Red
Write-Host "End time : " -NoNewline; Write-Host $EndTime -ForegroundColor Red
Write-Host "Duration : " -NoNewline; Write-Host $Duration -ForegroundColor Red -nonewline; Write-Host " second(s)"
Write-Host "`r"

 

Exemple du fichier Add-User.log créé automatiquement avec les logins des utilisateurs ajoutés dans le groupe AD :

[09/05/2020 16:24:45] ActiveDirectory module has been imported.
[09/05/2020 16:24:46] Administrateur has been added into the group : C_Helpdesk-JoinAD.
[09/05/2020 16:24:47] Invité has been added into the group : IT_Systeme.
[09/05/2020 16:24:48] Pierre has been added into the group : DSI_RW.

 

Cliquer ici pour visualiser un exemple du rapport Users-Report.html créé automatiquement.

 

Cliquer ici pour télécharger le fichier de style css.

 

Cliquer ici pour télécharger le script.