Ce petit didacticiel vous permettra de créer une base de données simple vous permettant de savoir qui est connecté sur quel ordinateur en temps et en heure, de récupérer des informations sur leur heure de login / logout, mais également (dans un prochain article) comment prendre la main sur l'ordinateur simplement en cliquant sur un lien hypertexte.

1. Créez un partage accessible à tous

996498e0237b318b0deb96b27f3fffa97853ef7af00a2104e735247c7eabf3e1_post-1-0-06531900-1397499668_1_

Comme les ordinateurs qui se connecteront / déconnecteront écriront dans un fichier de log, le chemin de ce fichier doit être partagé et accessible à chacun. Pour plus de praticité, créons un répértoire partagé. Pour cet exemple, supposons que nous avons crée un partage sur \\storage\logs$

2. Crééz un script de logon et de logout

Dans le repertoire NETLOGON de votre controlleur de domaine, créez deux fichiez :

  • Un nommé "login.bat" contenant ceci :
@echo off
ECHO %DATE%;%TIME%;%USERNAME%;%COMPUTERNAME%;%LOGONSERVER%;login >> \\storage\logs$\loginout.TXT
  • Un nommé "logout.bat" contenant ceci
@echo off
ECHO %DATE%;%TIME%;%USERNAME%;%COMPUTERNAME%;%LOGONSERVER%;logout >> \\storage\logs$\loginout.TXT

3. Liez ces scripts à une GPO

0e13d52f784c8acd0d96692a139d9791231871648e6decee549329c152f0d6a8_3122.wes081410031_5F00_4BADDD03_1_

Dans cet exemple, ces scripts sont liés à la Default Domain Policy.

Pour lier un scripts à ces GPO, ouvrez l'éditeur de stratégies de groupe, sélectionnez la Police par Défaut du Domaine, puis clic droit : Modifier.

Allez dans Configuration Utilisateur => Polices => Paramètres Windows => Scripts puis ajoutez les scripts de logon / logout, en précisant le chemin réseau (quelque chose comme \DC\netlogon\login.bat et pas le chemin local comme C:\Chemin\Vers\Script.ps1)

Sauvegardez les changements, et à partir de maintenant, vos ordinateurs vont commencer à enregistrer des données à chaque ouverture ou fermeture de session dans \storage\logs$\loginlogout.TXT

4. Créez le script Powershell et la tâche planifiée

49863c4b43b93e317c8b28a3ac472cfe16fc5ab8568076e5e1f43b601caae004_lgh

En utilisant mon script, vous pouvez récolter, obtenir les dernières informations du fichier de log et génerer un rapport en HTML.

Vous pouvez télécharger le script depuis mon répertoire git personnel.

#Requires -version 3
#Ce script requiert Powershell V3 ou supérieur pour fonctionner correctement, car l'export vers un fichier HTML ne fonctionnera pas correctement si c'est une version 2.

#Pensez à faire correspondre le chemin du fichier a ce que vous avez dans les .bat mis en GPO
$filename = "\\storage\logs$\loginout.TXT"
$logs = Get-Content $filename

# Cette partie est utilisée pour éviter d'avoir un trop gros fichier. Au dessus de 20000 entrées, il sauvegardera le contenu dans un autre fichier, puis réecrira le fichier avec les 10000 dernières. Vous pouvez changer ces valeurs à volonté.

if ($logs.count -gt 20000)
    {
    Copy-Item $filename $($filename + "_archive_" + $(Get-Date -Format dd_MM_yy) + ".txt")
    $logs[-10000..-1] | Out-File $filename -Force utf8
    }

$tableau = new-object System.Collections.ArrayList
$tableau2 = new-object System.Collections.ArrayList
#L'outil RSAT avec le module Active Directory n'est nécessaire que si vous lancer le script depuis un poste client. Si vous vous en servez depuis le serveur, ce doit être, celui ci doit être au moins un 2008 R2.
ipmo activedirectory

# Obtient la liste des utilisateurs depuis le controlleur de domaine. Necessaire pour retrouver le nom complet à partir du Sam Account Name.

$userlist = get-aduser -filter * | Select-Object -Property samaccountname,name
# Lisons le fichier ligne par ligne!
foreach ($log in $logs)
{
# J'utilise une REGEX pour retrouver les diverses informations de chaque ligne du fichier
    if ($log -match "(?<date>\d+/\d+/\d+);(?<heure>.+:\d+:\d+[,.]\d+);(?<compte>\S+);(?<pc>\S+);(?<serveur>\W{2}\w+);(?<action>.*$)")
        {
# Dans certains cas, le format de date diffère et affiche l'année en premier. Je vérifie juste si le format correspond à un format étranger, et le cas écheant, je réorganise le tout.

        $date = $Matches.date -split("/")
        if ($date[0].length -le 2)
            {
            $matches.date = [string]$($date[1]+"/"+$date[0]+"/"+$date[2])
            }

        $object = [pscustomobject]@{
        "Date" = $([datetime]$Matches.date)
        "Time" = $($($Matches.heure) -replace(",\d+",""))
        "Account" = $Matches.compte
        "Pc" = $matches.pc
        "Action" = $Matches.action
        "Server" = $Matches.serveur
        }

        $tableau.add($object) | Out-Null
        }
}
# Je trie le tableau récapitulatif, par date en descendant, puis je regroupe tout par nom d'ordinateur

$tableaugroupe = $tableau | sort-object -property @{Expression="Date";descending=$true} | Group-Object -Property "PC"

# Comme certains ordinateurs n'ont pas d'information de login / logout en fonction de leur utilisation (travail par VPN par exemple), je crée un objet avec des valeurs pré-définies pour ces cas

$itemsansvaleur = [pscustomobject]@{
        "Date" = $([datetime]"01/01/1901")
        "Time" = "00:00:00"
        }
# Pour chaque entrée dans le tableau trié, je prends le premier login et logout (qui sont les valeurs les plus récentes), puis je retrouve les informations dessus.

foreach ($entree in $tableaugroupe)
    {
    $lastlogin = $lastlogout = [PSCustomObject]
    try
    {
    $lastlogin = $($entree.group | Where-Object {$_.action -like "*login*"})[0]
    }
    catch
    {
        Write-Host "Erreur login sur $($entree.Name)"
        $lastlogin = $itemsansvaleur
    }
    try
    {
    $lastlogout = $($entree.group | Where-Object {$_.action -like "*logout*"})[0]
    }
    catch
    {
        Write-Host "Erreur logout sur $($entree.Name)"
        $lastlogout = $itemsansvaleur
    }
   # Je retrouve le nom complet

    $nom = $userlist | where-object {$_.samaccountname -eq $($lastlogin.account)} | Select-Object -ExpandProperty "Name"
    # Puis je crée l'objet.

    $object = [pscustomobject]@{
    "Compte" = $lastlogin.account
    "Name" = $nom
    "PC" = $entree.group[0].pc
    "Dernier Login" = get-date $(($lastlogin.Date).ToShortDateString()+" "+$lastlogin.heure) -Format "dd/MM/yy HH:mm:ss"
    "Serveur Login" = $lastlogin.server
    "Dernier Logout" = get-date $(($lastlogout.Date).ToShortDateString()+" "+$lastlogout.heure) -Format "dd/MM/yy HH:mm:ss"
    "Serveur Logout" = $lastlogout.server

        }
    $tableau2.Add($object) | out-null
    }

$date = Get-Date

# Je trie le tableau par ordinateur, puis je le convertit au format HTML. J'ai rajouté un fichier CSS pour rendre le tout plus joli. Si vous voulez donner un look plus sympa à votre fichier, créez juste un fichier nommé "tableaux.css" dans le même répertoire que le fichier HTML et laissez votre créativité travailler :D

$tableau2 | sort-object -Property "PC" | ConvertTo-Html -title "$($date.ToShortDateString()) $($date.ToShortTimeString())" -CssUri "tableaux.css" | Out-File "\\storage\logs$\logintohtml.html" -Encoding utf8 -Force

#Après cela, j'uploade le fichier sur un serveur web en me servant de .NET et en passant via le FTP. Ce n'est pas utile si vous stockez la page localement.

# Le login / password est en clair ici. Je ne le recommande pas, mais c'est uniquement à but d'exemple. Vous pouvez le rendre plus sur, mais ce n'est pas le but de ce script.

$credentials = new-object System.Net.NetworkCredential("username","password")
$webclient = new-object System.Net.WebClient
$webclient.Credentials = $credentials
$uri = New-Object System.Uri("ftp://webserver/www/logintohtml.html")
$webclient.uploadFile($uri,'\\storage\log$\logintohtml.html')

Le résultat est la génération d'un fichier html contenant diverses informations.

logintohtml_preview

J'ai amélioré depuis le script en ajoutant les résultats issus des pools DHCP de nos serveurs 2012, ainsi qu'ajouté des liens hypertexte sur les noms des PC pour pouvoir lancer directement la prise de main via Dameware dessus. Pour la tâche planifiée, vous pouvez regarder mon autre article expliquant comment créer et gérer les scripts Powershell. Pour un groupe de 150 utilisateurs, je fais tourner mon script toutes les 5 minutes et il ne prends pas plus de 30 secondes à s'exécuter.

Ajouter un commentaire

Article précédent Article suivant