Après avoir mis en place l'excellent outil Spiceworks sur le site d'un client, nous nous sommes rendus compte qu'une information importante dans la gestion du parc machines manquait : Les numéros de série des écrans rattachés au poste.

Heureusement pour nous : Powershell est là!

 Comment faire?

Les informations sur le matériel sont contenues dans le WMI, mais la liste est longue...

Pour nous aider dans nos recherches, le logiciel WMI Explorer est particulièrement utile. Et c'est ainsi que nous voyons dans le namespace root/WMI que nous avons une classe nommée WMIMonitorID et dans cette classe, la liste des écrans et leur numéro de série / produit associé.

wmi

Plus qu'a scripter tout ça pour obtenir les informations de tout le parc!

Nous devrons donc :

  • Obtenir l'intégralité des ordinateurs du parc, que nous filtrerons sur la date de dernier login, histoire de ne pas avoir les reliquats de pc.
  • Pinger pour vérifier que la machine répond bien sur le réseau, pour éviter de lancer des requêtes qui termineront en timeout et ralentiront le scripting, et filtrer à l'aide du TTL de retour les machines non windows.
  • Récupérer les informations et les enregistrer dans un format utilisable dans un autre script ou lisible par un utilisateur.

La commande Powershell issue de nos informations sera assez simple :

Get-wmiobject -Namespace "nom du namespace" -Class "nom de la classe" -computername "ordinateur"

En l'adaptant pour cet article, la commande sera donc la suivante :

Get-WmiObject -Namespace root\wmi -Class wmiMonitorID

Nous obtenons ainsi les informations sur les écrans rattachés à la machine.

resultatwmimonitor

Pour chaque écran nous avons une propriété "SerialNumberId" qui nous donne l'information recherchée... dans un format assez étrange!

wmimonitorsn

Il s'agit en fait des codes de caractères. Pour traduire cela et récupérer les bonnes informations, il suffit de faire une petite boucle foreach et d'ajouter la traduction de chaque caractère dans une variable.

wmimonitorconvertsn


Script Final

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

#déplacement dans le repertoires "mes documents" de l'utilisateur actuel
Set-Location $([Environment]::GetFolderPath("Mydocuments"))
#import du module activedirectory
ipmo activedirectory
#nous récupérons la liste des ordinateurs du domaine, en prenant également la dernière ouverture de session
$ordinateurs = Get-ADComputer -Filter * -Properties lastlogondate | Select-Object -Property name,lastlogondate
#nous filtrons à 4 mois en arrière
$ordinateurs = $ordinateurs | Where-Object {$_.lastlogondate -gt $((Get-Date).addmonths(-4))}
#creation d'un tableau
$tableau = New-Object System.Collections.ArrayList
$progress = 0
foreach ($ordinateur in $ordinateurs)
 {

  $progress++
  Write-Progress -Activity "Recherche d'écrans sur $($ordinateur.name) " -PercentComplete $($progress/$($ordinateurs.Count)*100) -Status "$progress / $($ordinateurs.count)"
  $objet = New-Object Psobject
  $objet |Add-Member -MemberType NoteProperty -Name "Ordinateur" -Value $ordinateur.name
  $ping = $null
  #nous pingons le poste.
  $ping = Test-Connection -ComputerName $ordinateur.name -Count 1
  #Si le TTL du poste est entre 65 et 128, c'est un poste windows. Nous continuons donc le script
  if ($ping -and $ping.responsetimetolive -gt 64 -and $ping.responsetimetolive -le 128)
  {
   $objet |Add-Member -MemberType NoteProperty -Name "Répond au ping" -Value "Oui"
   $moniteurs = $null

    $moniteurs = $null
    #on lance la requete WMI
    $moniteurs = Get-WmiObject -Namespace root\wmi -Class wmiMonitorID -ComputerName $($ordinateur.name)
   #Si le resultat de la commande precedente est une erreur, alors...    
   if (!$?)

    {
    Write-Host "Erreur!"
    $objet | Add-Member -MemberType NoteProperty -Name "WMI" -Value "ERREUR!!"
    }
   #Sinon...
   else
    {
    Write-Host "Aucune erreur"
    $objet | Add-Member -MemberType NoteProperty -Name "WMI" -Value ""
    }
    $i=0
   foreach ($moniteur in $moniteurs)
    {
    $i++
    #Le modele est la deuxième valeur de la propriété instancename.
    $modele = $moniteur.instancename.split("\")[1]
    $sn = $null
    #Récupération du SN puis ajout dans l'objet
    $moniteur.serialnumberid | % {$sn += [char]$_}
    $objet | Add-Member -MemberType NoteProperty -Name "Modèle ecran $i" -Value $modele
    $objet | Add-Member -MemberType NoteProperty -Name "SN ecran $i" -Value $sn

    }
    $i++
    for($i; $i -le 3;$i++)
    {
    $objet | Add-Member -MemberType NoteProperty -Name "Modèle ecran $i" -Value ""
    $objet | Add-Member -MemberType NoteProperty -Name "SN ecran $i" -Value ""

    }

  }
  #si le ttl est inférieur ou égal à 64, c'est un non windows
  elseif ($ping.responsetimetolive -ne $null -and $ping.responsetimetolive -le 64)
   {
   $objet |Add-Member -MemberType NoteProperty -Name "Répond au ping" -Value "Non Windows"
   }
  else 
   {
   $objet | Add-Member -MemberType NoteProperty -Name "Répond au ping" -Value "Non"
   }
 $null = $tableau.add($objet)

 }
$tableau | Export-Clixml -Path "ecrans.xml" 
$tableau | Export-Csv -Path "ecrans.csv" -NoTypeInformation -Encoding UTF8 -Force -Delimiter ";"

A noter que cette classe WMI n'existe que depuis Windows Vista. Si jamais vous avez des postes sous XP, vous ne pourrez pas remonter les informations recherchées!

Ajouter un commentaire

Article précédent Article suivant