Flash info

Les vrais admins utilisent la ligne de commande... (dixit le mag Windows IT Pro du 6/02/07) Avis aux amateurs pour affirmer leur virilité Surprised.
La suite est ici.

 
Accueil arrow Forum

Bienvenue sur le forum PowerShell-Scripting.com

 
Laurent Dardenne
Utilisateur

PowerShelleur Platinum
Messages: 5724
graph
Karma: 209  
[WMI]Comment détecter l'insertion d'un disque USB? - 18/06/09 10:17 Voici un code qui attend l'insertion d'un disque USB ou autre.

On crée une requête WQL d'événement, la classe Win32_PnPEntity concerne tous les éléments Plug and Play.
On indique un ensemble d'événement à l'aide de la classe d'événement "__InstanceOperationEvent" qui concerne la création,la modification et la suppression.
Code:

  $query =New-object System.Management.WqlEventQuery(            "__InstanceOperationEvent",         [TimeSpan]"0:0:1",        'TargetInstance isa "Win32_PnPEntity"')


Identique à :

SELECT * FROM __InstanceOperationEvent WITHIN 1
WHERE Targetinstance ISA 'Win32_PnPEntity

On crée un abonnement à des notifications d'événement temporaires :
Code:

  $watcher =new-object System.Management.ManagementEventWatcher $watcher.Query $query  #Gestion d'événement synchrone $evenement $watcher.WaitForNextEvent()


Puisque l'on attend un ensemble d'événement (création, modification et suppression), on détermine le type de l'événement reçu à l'aide de sa propriété __CLASS :
Code:

   #Détermine le type d'événement switch ($evenement.__Class) {     #Une nouvelle instance de la classe recherchée a été créée    "__InstanceCreationEvent"          {Write-Warning ("Nouvel élément Plug and Play détecté.")         #On créé une instance de la classe         #référencée par la propriété TargetInstance         #Nécessaire si on souhaite retrouver ses associations         $I=[wmi]"$($evenement.TargetInstance.__relpath)"       }     #Une instance de la classe recherchée vient d'être supprimée    "__InstanceDeletionEvent"  {       Write-Warning ("Un élément Plug and Play a été retiré.")        #L'instance référencée n'existe plus dans le référentiel, mais         #seulement comme copie dans la propriété TargetInstance.        #Difficile de retrouver les associations d'un objet inexistant...       $evenement.TargetInstance      }    default {Write-Warning "La classe d'événement __InstanceModificationEvent n'est pas gérée."}  } #Switch  #Libére les ressources $Watcher.Dispose() # Traitement nécessitant le device PnP ... 


Une fois cette mécanique mis en place on peut affiner la recherche, on peut vouloir filtrer plus précisément les événements :
Code:

  $query =New-object System.Management.WqlEventQuery(            "__InstanceOperationEvent",         [TimeSpan]"0:0:1",        '(__CLASS="__InstanceCreationEvent" or          __CLASS="__InstanceDeletionEvent") and         TargetInstance isa "Win32_PnPEntity"')


Puis préciser le type d'élément PnP
Code:

  #Win32_PnPEntity = tous les éléments PNP #Service="USBSTOR"=  de type USB Storage.  #Par exemple une clé USB $query =New-object System.Management.WqlEventQuery(            "__InstanceOperationEvent",         [TimeSpan]"0:0:1",        '(__CLASS="__InstanceCreationEvent" or          __CLASS="__InstanceDeletionEvent") and         TargetInstance isa "Win32_PnPEntity" and TargetInstance.Service="USBSTOR"')


Selon le contexte on peut vouloir disposer pour un même opération d'informations différentes, dans ce cas on change la classe ciblée.
Par exemple surveiller les disques, plutôt qu'un élément PnP :
Code:

  #disque $query =New-object System.Management.WqlEventQuery(            "__InstanceOperationEvent",         [TimeSpan]"0:0:1",        'TargetInstance isa "Win32_DiskDrive"')


Ou seulement les disques USB :
Code:

  $query =New-object System.Management.WqlEventQuery(          #On recherche les créations, modifications et suppressions d'instance         "__InstanceOperationEvent",          [TimeSpan]"0:0:1",         #On précise la classe recherchée, ici les disques USB        'TargetInstance isa "Win32_DiskDrive" and TargetInstance.InterfaceType="USB"')


Si on recheche les lecteurs, on accéde directement au nom d'unité.
Les lecteurs réseaux créés par la commande Net Use sont aussi concernés :
Code:

  # net use * \\HOSTNAME\C$ $query =New-object System.Management.WqlEventQuery(            "__InstanceOperationEvent",         [TimeSpan]"0:0:1",        'TargetInstance isa "Win32_LogicalDisk"')


Si on scrute les événements concernant la classe Win32_DiskDrive, on doit parcourir les associations pour récupérer la lettre de lecteur qui lui a été attribué, ou s'il contient plusieurs partitions les noms de lecteur ajoutés au système.
Une classe d’association définit les relations entre deux classes.
Un disque posséde une ou plusieurs partitions et à chaque partition est attribué un nom de lecteur, on doit donc interroger les objet suivants :
Win32_DiskDrive->Win32_DiskPartition->Win32_LogicalDisk

Code:

      #Une nouvelle instance de la classe Win32_DiskDrive a été créée    "__InstanceCreationEvent"   {       Write-Warning ("Nouveau lecteur détecté")       $I=[wmi]"$($evenement.TargetInstance.__relpath)"        #Recherche les associations de la classe         #Win32_DiskDrive à partir du disque détecté        #$Drives récupère les résultats d'un pipeline       $Drives=$I.psbase.GetRelationships()|         #on parcourt celles concernant les partitions du disque courant        where {$_.__class -eq "Win32_DiskDriveToDiskPartition"}|         #Pour chaque instance de type Win32_DiskDriveToDiskPartition         foreach {              #On créé une instance de Win32_DiskPartition,               #référencée par la propriété Dependent              #Sans cela on ne peut accéder à psbase.GetRelationships()             [wmi]"$($_.Dependent)"|              foreach {                 #Recherche les associations de la                 #classe Win32_DiskPartition à partir                 #de la partition courante                $_.psbase.GetRelationships()|                 #on parcourt celles concernant le                  #disque logique de la partition courante                where {$_.__class -eq "Win32_LogicalDiskToPartition"}|                 #Pour chaque instance de type Win32_LogicalDiskToPartition                 foreach {                    #On créé une instance de Win32_LogicalDisk,                     #référencée par la propriété Dependent.                    #On renvoie le nom d'unité qui lui a été attribuée                     ([wmi]"$($_.Dependent)").DeviceID                 }              }#Logical        }#Partition       Write-Warning ("`t unité : $drives")            }#Event Creation


Le principe de recherche dans les associations reste identique pour d'autres classes; Pour la classe Win32_PnPEntity je n'ai pas réussi à remonter jusqu'au disque...
Enfin la propriété Win32_PnPEntity.DeviceId peut servir à déterminer le type de device.

Message édité par: Laurent Dardenne, à: 18/06/09 11:58
Tutoriels PowerShell
  | | L'administrateur a désactivé l'accés public en écriture.
© 2020 PowerShell-Scripting.com