L'ajout d'utilisateurs dans des groupes de manière temporaire est un vrai casse tête.

Ces demandes correspondant en très grande majorité à un besoin d'accès à des ressources réservées à des groupes de sécurité, et bien souvent certains utilisateurs doivent se voir octroyés des droits afin de remplacer un collègue absent.

Autant il est un peu plus simple de gérer des demandes d'accès temporaires lorsque l'on est seul en charge de l'informatique d'une société, autant le fait d'avoir plusieurs personnes au sein du service support ou le fait d'être prestataire et d'avoir de multiples clients peut rendre la tâche compliquée...

Et inutile de dire que de laisser des accès à une personne qui ne devrait pas ou plus les avoir n'est pas quelque chose d'anodin. C'est une faille de sécurité importante, qui pourrait avoir des conséquences encore plus importantes! Partant de ce constat et du fait que mon ordinateur commençait à grouiller de post-it me rappelant que je devais retirer ou ajouter en date du X l'utilisateur Y au groupe W, je me suis mis en tête de créer quelque chose de "simple" et efficace pour permettre de programmer des ajouts et des suppressions d'utilisateurs à des groupes à des dates précises. Afin de permettre à tout un chacun du service informatique de se servir de mon nouveau jouet, j'ai également programmé une interface utilisateur intuitive. Ce script a été testé et est fonctionnel sur Windows Server 2008R2 et 2012, doit fonctionner sur des versions supérieures.

L'interface graphique

L'interface en elle même vous est présentée ci-dessous. Elle comporte 8 points importants que je vais décrire.

form

  1. Le choix de l'utilisateur : Utilisé pour savoir à qui appliquer le(s) groupe(s)
  2. Les dates de début et fin : Afin de savoir quand ajouter et retirer l'autorisation
  3. La liste des groupes : Cochable, vous permet de choisir de multiples groupes à ajouter. La croix sur le dessus décoche tout ce qui a été selectionné.
  4. Le bouton d'ajout : Utilisé pour mettre dans la liste récapitulative (point 7) le ou les entrées.
  5. Le bouton retrait : La ou les lignes selectionnées de la grille (7) sont retirées
  6. Le bouton retirer tout : Vide la liste de tout son contenu.
  7. La grille de données : Permet de voir les ajouts qui seront faits lors de la validation des données.
  8. Le bouton OK : Bien évidemment, c'est pour valider le tout.

Lorsque le bouton OK est validé, un fichier XML est créé dans un répertoire défini en entête du script. Ce fichier XML contient l'intégralité des entrées de la Datagridview et est traité dans un second script qui tourne en tache planifiée, et qui ajoute ou retire l'appartenance d'un ou plusieurs groupes aux utilisateurs qui ont dépassé les dates de début ou de fin. Le nom de chaque label ou de colonne de la grille de données est changeable afin d'être adaptable au client, à la seule condition de ne pas modifier les noms de champs de la grille de données une fois le script en production.

Le script de planification

Ce script doit tourner en tâche planifiée, et être executé une fois par jour. Il va récupérer les fichiers XML crées par le formulaire, ainsi que les anciens fichiers déjà partiellement traités (Par exemple un ajout dans un groupe qui attends une fin), vérifier chaque date et ajouter chaque entrée qui n'a pas déjà été faite, commençant par ajouter dans les groupes, puis supprimer (ainsi si le script n'a pas pu tourner pendant X jours et que des modifications se font, cela se terminera par des retraits de groupes, et évitera de laisser une autorisation permanente.)

Des lors qu'il exécute une action, il ajoute une notation à l'objet représentant les ajouts / suppression en attente permettant de savoir si oui ou non une action a déjà été faite.

Si une erreur ou une incohérence se présentent, les exceptions sont affichées dans deux fichiers error.txt et warning.txt, permettant de détecter tout problème.

Afin de pouvoir rajouter à tout cela une autre tracabilité, je vous propose de reprendre également mon article qui permet de lister les modifications faites sur les groupes Active Directory entre deux exécutions du script.

Et maintenant...

LES SCRIPTS

Vous pouvez télécharger les 2 scripts (gui et script en planification) sur mon espace git personnel.

1. L'interface utilisateur

#La variable $path représente le repertoire dans lequel les données seront sauvegardées. Changez le également dans le script de planification pour qu'il corresponde à celui renseigné ici

$path = "\\nas\ScriptPS\Workspaces\TemporaryUserToGroup"

#Le nom des colonnes. Changez le à votre guise, mais ne le changez plus une fois que le script est mis en production

$columnsnames = @("Util.","Groupe","De","Jusque")

#Labels que vous pouvez changer à votre guise
$labelusername = "Util."
$labelgroupname = "Groupe"
$labelfromname = "De"
$labeluntilincluded = "Jusque (inclus)"
$labelform = "Ajout de groupe temporaire by Nicolas LANG. lang.nicolas54 arobase gmail .com"
$popupmessage = "Choisissez un utilisateur et un ou plusieurs groupes"

#Différents messages d'erreur que vous pouvez modifier si besoin est 

$aderror = "Impossible d'obtenir des informations de groupe ou d'utilisateur. Vérifiez que le module AD pour Powershell est activé ou que le controleur de domaine est joignable"
$nopathcreated = "Impossible de créer $path"
try
{
 $users = Get-ADUser -filter 'enabled -eq $true'
 $groups = Get-ADGroup -filter *
}
catch
{
 Write-Output $aderror
 Start-Sleep -Seconds 5
 throw("AD Error")
}
$datestart = Get-Date -Format yyyy-MM-dd
$array = New-Object System.Collections.ArrayList

If (!(Test-Path $path))
{
 Try
 {
  New-Item $path -ItemType Folder -Force
 }
 Catch
 {
  throw($nopathcreated)

 }
}

#region Import the Assemblies
[reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null
[reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null
#endregion

#region Generated Form Objects
$bds = New-Object System.Windows.Forms.BindingSource
$form1 = New-Object System.Windows.Forms.Form
$groupBox_permatemp = New-Object System.Windows.Forms.GroupBox
$radioButton_temporary = New-Object System.Windows.Forms.RadioButton
$radioButton_permanent = New-Object System.Windows.Forms.RadioButton
$label4 = New-Object System.Windows.Forms.Label
$button_OK = New-Object System.Windows.Forms.Button
$button3 = New-Object System.Windows.Forms.Button
$button_remove = New-Object System.Windows.Forms.Button
$button_add = New-Object System.Windows.Forms.Button
$listBox_results = New-Object System.Windows.Forms.ListBox
$label_from = New-Object System.Windows.Forms.Label
$dateTimePicker2 = New-Object System.Windows.Forms.DateTimePicker
$dateTimePicker1 = New-Object System.Windows.Forms.DateTimePicker
$label_group = New-Object System.Windows.Forms.Label
$label_utilisateur = New-Object System.Windows.Forms.Label
$comboBox1 = New-Object System.Windows.Forms.ComboBox
$datagridview1 = New-Object System.Windows.Forms.datagridview
$checkedListBox1 = New-Object System.Windows.Forms.CheckedListBox
$button_uncheck = New-Object System.Windows.Forms.Button
$InitialFormWindowState = New-Object System.Windows.Forms.FormWindowState
#endregion Generated Form Objects

#region fonctions
function Check-Date{
if ([datetime]$dateTimePicker1.value -gt [datetime]$dateTimePicker2.Value)
    {
        $dateTimePicker2.value = $dateTimePicker1.Value
    }
}

Function Show-popup([string]$message){

    $popup = New-Object -ComObject Wscript.Shell
    $popup.Popup($message,0,"Erreur",0x0)

}

Function Check-Array($row, $comparearray){
    $return = $false
    foreach ($line in $comparearray)
    {
        if (!(Compare-Object $row.psobject.properties $line.psobject.properties))
        {
            $return = $true
            return $return
        }

    }

    return $return
}
#endregion

#show_sidebar: false
visible: false
----------------------------------------------
#Generated Event Script Blocks
#show_sidebar: false
visible: false
----------------------------------------------
#Provide Custom Code for events specified in PrimalForms.
$handler_button_add_MouseClick= 
{

}

$handler_dateTimePicker2_ValueChanged= 
{
    Check-Date

}

$button_OK_OnClick= 
{

 if ($array.Count -gt 0)
 {
  $dateTime = "$(Get-Date -Format yyyyMMdd_HHmmss).xml"
  $array | Export-Clixml (Join-Path $path $dateTime)
  $form1.Close()
 }

}

$handler_button3_MouseClick= 
{

}

$handler_dateTimePicker1_ValueChanged= 
{
    Check-Date
}

$handler_button_uncheck_Click=
{
 foreach ($checked in $checkedListBox1.CheckedIndices)
 {
  $checkedListBox1.SetItemChecked($checked,$False)
 }
}

$handler_radioButton_permanent_CheckedChanged= 
{
    if ($radioButton_permanent.Checked)
    {
        $dateTimePicker1.Enabled = $False
        $dateTimePicker2.Enabled = $False
    }
    else
    {
        $dateTimePicker1.Enabled = $True
        $dateTimePicker2.Enabled = $True
    }
}

$button_remove_OnClick= 
{

 foreach ($selectedrow in $datagridview1.SelectedRows)
 {
     $index= $array.IndexOf(($array | Where-Object {$_ -eq $selectedrow.DataBoundItem}))
     $array.RemoveAt($index)

 }
 $datagridview1.DataSource = $null
 $bds.DataSource = $null
 $bds.DataSource = $array
 $datagridview1.DataSource = $bds

}

$handler_button_OK_MouseClick= 
{
    $array | Export-Clixml 

}

$button3_OnClick= 
{

 $array.Clear()
 $datagridview1.DataSource = $null
 $bds.DataSource = $null
 $bds.DataSource = $array
 $datagridview1.DataSource = $bds

#TODO: Place custom script here

}

$handler_button_remove_MouseClick= 
{
#TODO: Place custom script here

}

$button_add_OnClick= 
{

    if ($checkedListBox1.SelectedItems.Count -gt 0 -and $comboBox1.SelectedItem -ne $null)
    {
        Foreach ($item in $($checkedListBox1.CheckedItems))
        {

            $newline = [pscustomobject]@{$columnsnames[0]=$comboBox1.SelectedItem;$columnsnames[1]=$item;$columnsnames[2]=([datetime]$dateTimePicker1.Value).ToShortDateString();$columnsnames[3]=([datetime]$dateTimePicker2.Value).ToShortDateString()}
            $result = (Check-Array -row $newline -comparearray $array)
            if (!($result))
            {
                $array.add($newline)
            }
        }

  $datagridview1.DataSource = $null
  $bds.DataSource = $null
  $bds.DataSource = $array
  $datagridview1.DataSource = $bds

    }
    else
    {
        Show-Popup $popupmessage
    }

#TODO: Place custom script here

}

$OnLoadForm_StateCorrection=
{#Correct the initial state of the form to prevent the .Net maximized form issue
 $form1.WindowState = $InitialFormWindowState
    $comboBox1.items.AddRange($($users | select-object -ExpandProperty samaccountname | sort-object))
    $checkedListBox1.items.AddRange($($groups | select-object -ExpandProperty name | sort-object))
}

#show_sidebar: false
visible: false
----------------------------------------------
#region Generated Form Code
$form1.AcceptButton = $button_OK
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 261
$System_Drawing_Size.Width = 1033
$form1.ClientSize = $System_Drawing_Size
$form1.DataBindings.DefaultDataSourceUpdateMode = 0
$form1.MaximizeBox = $False
$form1.Name = "form1"
$form1.ShowIcon = $False
$form1.Text = $labelform

$button_uncheck.BackColor = [System.Drawing.Color]::FromArgb(255,255,255,255)
$button_uncheck.DataBindings.DefaultDataSourceUpdateMode = 0
$button_uncheck.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",6,0,3,0)
$button_uncheck.ForeColor = [System.Drawing.Color]::FromArgb(255,255,0,0)
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 444
$System_Drawing_Point.Y = 42
$button_uncheck.Location = $System_Drawing_Point
$button_uncheck.Name = "button_uncheck"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 17
$System_Drawing_Size.Width = 23
$button_uncheck.Size = $System_Drawing_Size
$button_uncheck.TabIndex = 13
$button_uncheck.Text = "X"
$button_uncheck.UseVisualStyleBackColor = $False
$button_uncheck.add_Click($handler_button_uncheck_Click)
$form1.Controls.Add($button_uncheck)

$dataGridView1.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 520
$System_Drawing_Point.Y = 8
$dataGridView1.Location = $System_Drawing_Point
$dataGridView1.Name = "dataGridView1"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 241
$System_Drawing_Size.Width = 449
$dataGridView1.Size = $System_Drawing_Size
$dataGridView1.TabIndex = 12
$dataGridView1.SelectionMode = 1
$dataGridView1.AllowUserToAddRows = $False
$dataGridView1.AllowUserToDeleteRows = $False
$bds.DataSource = $array
$datagridview1.DataSource = $bds

$form1.Controls.Add($dataGridView1)

$groupBox_permatemp.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 14
$System_Drawing_Point.Y = 68
$groupBox_permatemp.Location = $System_Drawing_Point
$groupBox_permatemp.Name = "groupBox_permatemp"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 74
$System_Drawing_Size.Width = 200
$groupBox_permatemp.Size = $System_Drawing_Size
$groupBox_permatemp.TabIndex = 2
$groupBox_permatemp.TabStop = $False

$form1.Controls.Add($groupBox_permatemp)

$radioButton_temporary.Checked = $True
$radioButton_temporary.DataBindings.DefaultDataSourceUpdateMode = 0

$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 7
$System_Drawing_Point.Y = 38
$radioButton_temporary.Location = $System_Drawing_Point
$radioButton_temporary.Name = "radioButton_temporary"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 24
$System_Drawing_Size.Width = 104
$radioButton_temporary.Size = $System_Drawing_Size
$radioButton_temporary.TabIndex = 3
$radioButton_temporary.TabStop = $True
$radioButton_temporary.Text = "Temporaire"
$radioButton_temporary.UseVisualStyleBackColor = $True

$groupBox_permatemp.Controls.Add($radioButton_temporary)

$radioButton_permanent.DataBindings.DefaultDataSourceUpdateMode = 0

$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 7
$System_Drawing_Point.Y = 10
$radioButton_permanent.Location = $System_Drawing_Point
$radioButton_permanent.Name = "radioButton_permanent"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 24
$System_Drawing_Size.Width = 104
$radioButton_permanent.Size = $System_Drawing_Size
$radioButton_permanent.TabIndex = 2
$radioButton_permanent.TabStop = $True
$radioButton_permanent.Text = "Permanent"
$radioButton_permanent.UseVisualStyleBackColor = $True
$radioButton_permanent.add_CheckedChanged($handler_radioButton_permanent_CheckedChanged)

$groupBox_permatemp.Controls.Add($radioButton_permanent)
$groupBox_permatemp.Visible = $False

$label4.BorderStyle = 1
$label4.DataBindings.DefaultDataSourceUpdateMode = 0

$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 14
$System_Drawing_Point.Y = 198
$label4.Location = $System_Drawing_Point
$label4.Name = "label4"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 23
$System_Drawing_Size.Width = 200
$label4.Size = $System_Drawing_Size
$label4.TabIndex = 9
$label4.Text = $labeluntilincluded
$label4.TextAlign = 32

$form1.Controls.Add($label4)

$button_OK.DataBindings.DefaultDataSourceUpdateMode = 0
$button_OK.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",8,0,3,0)

$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 975
$System_Drawing_Point.Y = 8
$button_OK.Location = $System_Drawing_Point
$button_OK.Name = "button_OK"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 31
$System_Drawing_Size.Width = 55
$button_OK.Size = $System_Drawing_Size
$button_OK.TabIndex = 11
$button_OK.Text = "OK"
$button_OK.UseVisualStyleBackColor = $True
$button_OK.add_Click($button_OK_OnClick)
#$button_OK.add_MouseClick($handler_button_OK_MouseClick)

$form1.Controls.Add($button_OK)

$button3.DataBindings.DefaultDataSourceUpdateMode = 0

$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 472
$System_Drawing_Point.Y = 182
$button3.Location = $System_Drawing_Point
$button3.Name = "button3"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 39
$System_Drawing_Size.Width = 42
$button3.Size = $System_Drawing_Size
$button3.TabIndex = 9
$button3.Text = "<<"
$button3.UseVisualStyleBackColor = $True
$button3.add_Click($button3_OnClick)
$button3.add_MouseClick($handler_button3_MouseClick)

$form1.Controls.Add($button3)

$button_remove.DataBindings.DefaultDataSourceUpdateMode = 0

$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 472
$System_Drawing_Point.Y = 138
$button_remove.Location = $System_Drawing_Point
$button_remove.Name = "button_remove"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 38
$System_Drawing_Size.Width = 42
$button_remove.Size = $System_Drawing_Size
$button_remove.TabIndex = 8
$button_remove.Text = "<"
$button_remove.UseVisualStyleBackColor = $True
$button_remove.add_Click($button_remove_OnClick)
$button_remove.add_MouseClick($handler_button_remove_MouseClick)

$form1.Controls.Add($button_remove)

$button_add.DataBindings.DefaultDataSourceUpdateMode = 0

$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 472
$System_Drawing_Point.Y = 42
$button_add.Location = $System_Drawing_Point
$button_add.Name = "button_add"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 34
$System_Drawing_Size.Width = 42
$button_add.Size = $System_Drawing_Size
$button_add.TabIndex = 7
$button_add.Text = ">"
$button_add.UseVisualStyleBackColor = $True
$button_add.add_Click($button_add_OnClick)
$button_add.add_MouseClick($handler_button_add_MouseClick)

$form1.Controls.Add($button_add)

$listBox_results.DataBindings.DefaultDataSourceUpdateMode = 0
$listBox_results.FormattingEnabled = $True
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 543
$System_Drawing_Point.Y = 9
$listBox_results.Location = $System_Drawing_Point
$listBox_results.Name = "listBox_results"
$listBox_results.SelectionMode = 3
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 238
$System_Drawing_Size.Width = 238
$listBox_results.Size = $System_Drawing_Size
$listBox_results.TabIndex = 10

$form1.Controls.Add($listBox_results)

$label_from.BorderStyle = 1
$label_from.DataBindings.DefaultDataSourceUpdateMode = 0

$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 14
$System_Drawing_Point.Y = 149
$label_from.Location = $System_Drawing_Point
$label_from.Name = "label_from"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 23
$System_Drawing_Size.Width = 200
$label_from.Size = $System_Drawing_Size
$label_from.TabIndex = 6
$label_from.Text = $labelfromname
$label_from.TextAlign = 32

$form1.Controls.Add($label_from)

$dateTimePicker2.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 14
$System_Drawing_Point.Y = 224
$dateTimePicker2.Location = $System_Drawing_Point
$dateTimePicker2.Name = "dateTimePicker2"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 20
$System_Drawing_Size.Width = 200
$dateTimePicker2.Size = $System_Drawing_Size
$dateTimePicker2.TabIndex = 5
$dateTimePicker2.add_ValueChanged($handler_dateTimePicker2_ValueChanged)

$form1.Controls.Add($dateTimePicker2)

$dateTimePicker1.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 14
$System_Drawing_Point.Y = 175
$dateTimePicker1.Location = $System_Drawing_Point
$dateTimePicker1.MinDate = "2015-09-03"
$dateTimePicker1.Name = "dateTimePicker1"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 20
$System_Drawing_Size.Width = 200
$dateTimePicker1.Size = $System_Drawing_Size
$dateTimePicker1.TabIndex = 4
$dateTimePicker1.add_ValueChanged($handler_dateTimePicker1_ValueChanged)

$form1.Controls.Add($dateTimePicker1)

$label_group.BorderStyle = 1
$label_group.DataBindings.DefaultDataSourceUpdateMode = 0

$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 237
$System_Drawing_Point.Y = 9
$label_group.Location = $System_Drawing_Point
$label_group.Name = "label_group"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 23
$System_Drawing_Size.Width = 228
$label_group.Size = $System_Drawing_Size
$label_group.TabIndex = 3
$label_group.Text = $labelgroupname
$label_group.TextAlign = 32

$form1.Controls.Add($label_group)

$label_utilisateur.BorderStyle = 1
$label_utilisateur.DataBindings.DefaultDataSourceUpdateMode = 0

$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 14
$System_Drawing_Point.Y = 9
$label_utilisateur.Location = $System_Drawing_Point
$label_utilisateur.Name = "label_utilisateur"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 23
$System_Drawing_Size.Width = 200
$label_utilisateur.Size = $System_Drawing_Size
$label_utilisateur.TabIndex = 2
$label_utilisateur.Text = $labelusername
$label_utilisateur.TextAlign = 32

$form1.Controls.Add($label_utilisateur)

$comboBox1.DropDownStyle = 2
$comboBox1.DataBindings.DefaultDataSourceUpdateMode = 0
$comboBox1.FormattingEnabled = $True
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 13
$System_Drawing_Point.Y = 45
$comboBox1.Location = $System_Drawing_Point
$comboBox1.Name = "comboBox1"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 21
$System_Drawing_Size.Width = 201
$comboBox1.Size = $System_Drawing_Size
$comboBox1.TabIndex = 1

$form1.Controls.Add($comboBox1)

$checkedListBox1.CheckOnClick = $True
$checkedListBox1.DataBindings.DefaultDataSourceUpdateMode = 0
$checkedListBox1.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",8,0,3,0)
$checkedListBox1.FormattingEnabled = $True
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 237
$System_Drawing_Point.Y = 59
$checkedListBox1.Location = $System_Drawing_Point
$checkedListBox1.Name = "checkedListBox1"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 184
$System_Drawing_Size.Width = 228
$checkedListBox1.Size = $System_Drawing_Size
$checkedListBox1.TabIndex = 6

$form1.Controls.Add($checkedListBox1)

#endregion Generated Form Code

#Save the initial state of the form
$InitialFormWindowState = $form1.WindowState
#Init the OnLoad event to correct the initial state of the form
$form1.add_Load($OnLoadForm_StateCorrection)

$form1.ShowDialog()| Out-Null

2. Le script planificateur

$ErrorActionPreference = "Stop"
#Faites correspondre $path avec la même valeur que dans le script d'interface utilisateur
$path = "\\nas\ScriptPS\Workspaces\TemporaryUserToGroup"
$filelist = Get-ChildItem $path
#Les fichiers XML sont générés avec un identifiant numérique. La regex va filtrer selon ce critère
$totreat =  $filelist | Where-Object {$_.Name -match "^\p{Nd}.+.xml$"}
#Les fichiers à moitié traités commencent par un A puis un identifiant numérique. La encore, la regex va filtrer.
$resultarrayimports = $filelist | Where-Object {$_.Name -match "^A\p{Nd}.+.xml$"}
$resultarray = New-Object System.Collections.ArrayList
$global:headers = $null

function Update-File
{
 param($from = $null,$until = $null)
 $result = $null
 if ($from -ne $null)
 {
  $result = $resultarray.IndexOf($from)

  if ($result -eq -1)
  {
   "$(get-date -format yyyyMMdd_HHmmss) : Update from FROM - $($line.$($global:headers[1])) / $($line.$($global:headers[2])) => $($Error[0].Exception.Message)" >> "$path\warning.txt"

   throw("No result for FROM in the result array")
  }
  else
  {
   $resultarray[$result].$($global:headers[2]+"_checked") = "X"
  }
 }
 elseif ($until -ne $null)
 {
  $result = $resultarray.IndexOf($until)

  if ($result -eq -1)
  {
      "$(get-date -format yyyyMMdd_HHmmss) : Update from UNTIL - $($line.$($global:headers[1])) / $($line.$($global:headers[2])) => $($Error[0].Exception.Message)" >> "$path\warning.txt"

      throw("No result for UNTIL in the result array")
  }
  else
  {
   $resultarray[$result].$($global:headers[3]+"_checked") = "X"
  }
 }
 else
 {
  "$(get-date -format yyyyMMdd_HHmmss) : A Null value came to the function => $($Error[0].Exception.Message)" >> "$path\warning.txt"
  throw("Null Value from function")
 }

}

#Récupération des fichiers et ajout des colonnes de check date
foreach ($file in $totreat)
{
 try
 {
  $array = Import-Clixml $file.FullName
 }
 catch
 {
  "$(get-date -format yyyyMMdd_HHmmss) : $($file.FullName) => $($Error[0].Exception.Message)" >> "$path\error.txt"
  throw("Error while importing")
 }
 $global:headers = $array[0].psobject.Properties.name
 $array | Add-Member -MemberType NoteProperty -Name $($global:headers[2]+"_checked") -Value $null
 $array | Add-Member -MemberType NoteProperty -Name $($global:headers[3]+"_checked") -Value $null
 $array | Add-Member -MemberType NoteProperty -Name "Original_file" -Value $file.Name
 foreach ($entry in $array)
 {
  $resultarray.Add($entry) | Out-Null
 }
}
#Récupère les headers si aucun fichier créé depuis la GUI n'existe.
if ($global:headers -eq $null)
{
 #Tente depuis des fichiers déja importés
 try
 {
  $array = Import-Clixml ($filelist | Where-Object {$_.Name -like "IMPORTED_*"} | Select-Object -First 1).fullname
  $Global:headers = $array[0].psobject.Properties.name

 }
 catch
 {
  #Si rien, tente depuis un fichier Axxxxx.xml issu d'un $resultarray précedent
  try
  {
   $array = Import-Clixml $($resultarrayimports | Select-Object -First 1).FullName
   $global:headers = $array[0].psobject.Properties.name
  }
  catch
  {
   "$(get-date -format yyyyMMdd_HHmmss) : No file to import" >> "$path\warning.txt"
   throw("Nothing to import!")
  }
 }

}

#Rajoute chaque enregistrement déja exporté auparavant

if ($resultarrayimports -ne $null)
{
 $import = Import-Clixml $resultarrayimports.FullName
 foreach ($result in $import)
 {
  $resultarray.Add($result)
 }
 foreach ($result in $resultarrayimports)
 {
  Move-Item $result.FullName (join-path $path $("IMPORTED_"+ $($result.Name)))
 }
}

#Renomme chaque fichier totreat, considéré comme intégré, pour ne plus être pris en compte au prochain passage du script
foreach ($file in $totreat)
{
 $newname = "IMPORTED_" + $file.Name
 try
 {

  Move-Item $file.FullName (Join-Path $path $newname) -Force

 }
 catch
 {
  "$(get-date -format yyyyMMdd_HHmmss) : $($file.FullName) / $newname => $($Error[0].Exception.Message)" >> "$path\error.txt"
  throw("Error while moving item")

 }
}

#Checke de chaque entrée dans resultarray

$date = get-date
foreach ($line in $resultarray)
{
 $line
 if ((Get-Date $($line.$($global:headers[2]))).date -le $date.Date -and $line.$($global:headers[2]+"_checked") -eq $null)
 {

  try 
  {
   Add-ADGroupMember $line.$($global:headers[1]) $line.$($global:headers[0])
            Write-output "Adding $($line.$($global:headers[0])) to $($line.$($global:headers[1])) / $($line.$($global:headers[2])) to $($line.$($global:headers[3]))"
  }
  catch [Microsoft.ActiveDirectory.Management.ADException]
  {

   "$(get-date -format yyyyMMdd_HHmmss) : $($line.$($global:headers[1])) / $($line.$($global:headers[0])) => $($Error[0].Exception.Message)" >> "$path\warning.txt"
  }
  catch
  {
   "$(get-date -format yyyyMMdd_HHmmss) : $($line.$($global:headers[1])) / $($line.$($global:headers[0])) => $($Error[0].Exception.Message)" >> "$path\error.txt"
   throw("Erreur!")
  }

  Update-File -from $line

 }
 if ((Get-Date $($line.$($global:headers[3]))).date -lt $date.Date -and $line.$($global:headers[3]+"_checked") -eq $null)
 {
  try 
  {
            Write-output "Removing $($line.$($global:headers[0])) from $($line.$($global:headers[1])) / $($line.$($global:headers[2])) to $($line.$($global:headers[3]))"
      Remove-ADGroupMember $line.$($global:headers[1]) $line.$($global:headers[0]) -Confirm:$false
  }
  catch [Microsoft.ActiveDirectory.Management.ADException]
  {
   "Account not member of the group "
   "$(get-date -format yyyyMMdd_HHmmss) : $($line.$($global:headers[1])) / $($line.$($global:headers[0])) => $($Error[0].Exception.Message)" >> "$path\warning.txt"
  }
  catch
  {
   "$(get-date -format yyyyMMdd_HHmmss) : $($line.$($global:headers[1])) / $($line.$($global:headers[0])) => $($Error[0].Exception.Message)" >> "$path\error.txt"
   throw("Erreur!")
  }

  Update-File -until $line

 }
}

#Clean des entrées

$indexarray = @()
$index = 0

foreach ($line in $resultarray)
{

    if ($line.$($global:headers[2]+"_checked") -eq "X" -and $line.$($global:headers[3]+"_checked") -eq "X")
    {
        $indexarray += $index
    }
$index++
}

$indexarray = $indexarray | Sort-Object -Descending

foreach ($entry in $indexarray)
{
    $resultarray.RemoveAt($entry)
}

$rafile = "A"+(Get-Date).Ticks+".xml"

if ($resultarray.Count -gt 0)
{
 $resultarray | Export-Clixml (Join-Path $path $rafile)
}

Edit du 14/09/2015 : Visiblement mon travail a bien plu, puisque sur le forum communautaire de Spiceworks, mon travail a été promu par la communauté, et me voici en première page du site et en toute première position qui plus est! Joie!

spiceworks_posted

Ajouter un commentaire

Article précédent Article suivant