Démarrage d'une tâche planifiée en détectant la connexion du périphérique USB

24

Je sais qu'il a été discuté qu'il n'est pas possible de démarrer une application à partir d'un lecteur USB lors de la connexion en raison des limitations de l'exécution automatique (ou de la lecture automatique ??) dans Win 7. Mais il est possible de créer une tâche planifiée ayant un déclencheur de type d'événement . Il doit sûrement y avoir un événement se produisant lorsque le lecteur - ou tout périphérique USB, d'ailleurs - est connecté.

Quelqu'un a-t-il la moindre idée de l'ID d'événement à utiliser? Ou du moins quel type d'événement? Où puis-je trouver l'événement dans l'Observateur d'événements?

gemisigo
la source

Réponses:

17

Le thread Task Scheduler: Comment synchroniser automatiquement ma clé USB? a cette réponse par un utilisateur appelé monotone, qui utilise PowerShell avec le Planificateur de tâches:

J'avais la même question que vous et j'ai travaillé sur quelque chose avec PowerShell (scripts intégrés Windows) en utilisant les techniques du Scripting Guy Blog ici et ici . Le script s'exécute en continu en tant que processus d'arrière-plan, que vous pouvez démarrer à l'ouverture de session système avec le planificateur de tâches. Le script sera notifié chaque fois qu'un nouveau lecteur est branché et fera quelque chose (ici vous configurez le script plutôt que la tâche). Comme il est essentiellement suspendu pendant l'attente du prochain lecteur branché, vous ne devriez pas trouver qu'il prend beaucoup de ressources. J'y vais:

1) Démarrez Powershell ISE, qui se trouve dans votre menu Démarrer sous Accessoires / Windows Powershell. 2) Copiez et collez les éléments suivants dans Powershell:

#Requires -version 2.0
Register-WmiEvent -Class win32_VolumeChangeEvent -SourceIdentifier volumeChange
write-host (get-date -format s) " Beginning script..."
do{
$newEvent = Wait-Event -SourceIdentifier volumeChange
$eventType = $newEvent.SourceEventArgs.NewEvent.EventType
$eventTypeName = switch($eventType)
{
1 {"Configuration changed"}
2 {"Device arrival"}
3 {"Device removal"}
4 {"docking"}
}
write-host (get-date -format s) " Event detected = " $eventTypeName
if ($eventType -eq 2)
{
$driveLetter = $newEvent.SourceEventArgs.NewEvent.DriveName
$driveLabel = ([wmi]"Win32_LogicalDisk='$driveLetter'").VolumeName
write-host (get-date -format s) " Drive name = " $driveLetter
write-host (get-date -format s) " Drive label = " $driveLabel
# Execute process if drive matches specified condition(s)
if ($driveLetter -eq 'Z:' -and $driveLabel -eq 'Mirror')
{
write-host (get-date -format s) " Starting task in 3 seconds..."
start-sleep -seconds 3
start-process "Z:\sync.bat"
}
}
Remove-Event -SourceIdentifier volumeChange
} while (1-eq1) #Loop until next event
Unregister-Event -SourceIdentifier volumeChange

3) Vous devez modifier le script ci-dessus pour indiquer au script quel lecteur rechercher et quoi exécuter. Les deux lignes à modifier sont:

if ($driveLetter -eq 'Z:' -and $driveLabel -eq 'Mirror')

Mon disque dur USB nommé «Mirror» est défini comme le lecteur Z :. Vous pouvez simplement l'utiliser if ($driveLabel -eq 'MyDiskLabel')si vous ne vous souciez pas de la lettre.

start-process "Z:\sync.bat"

Chemin de la tâche que vous voulez faire. Dans mon exemple, j'ai créé un fichier de commandes sur ma clé USB qui démarre 3-4 lignes de commande de tâches de sauvegarde.

4) Lorsque vous avez terminé, enregistrez votre script quelque part (extension .ps1), puis allez créer une tâche dans le Planificateur de tâches pour que votre script s'exécute en arrière-plan. Le mien ressemble à ceci:

  • Déclencheur: à la connexion
  • Action: démarrer un programme
  • Programme / script: PowerShell
  • Ajoutez des arguments: -ExecutionPolicy Unrestricted -File "D:\Stuff\Backup script.ps1"

5) Voilà!

6) Des trucs supplémentaires:

Si vous souhaitez que votre fenêtre de script soit masquée, utilisez ces arguments:

  • Ajoutez des arguments:
    -WindowStyle Hidden -ExecutionPolicy Unrestricted -File "D:\Stuff\Backup script.ps1"

Si vous souhaitez générer les messages de script dans un fichier journal (qui est écrasé à chaque démarrage du script, c'est-à-dire à la connexion), utilisez l'action de tâche suivante:

  • Programme / script: cmd
  • Ajouter des arguments:
    /c powershell -WindowStyle Hidden -ExecutionPolicy Unrestricted -File "D:\Stuff\Backup script.ps1" > "D:\Stuff\script log.txt "

Chaque fois que vous souhaitez mettre fin au script masqué en cours d'exécution, vous pouvez terminer le processus "Powershell" dans le Gestionnaire des tâches.

Le seul inconvénient est que rien ne fonctionnera lorsque vous démarrez votre ordinateur avec le lecteur déjà branché. (Le script pourrait être modifié pour effectuer une première vérification au départ, mais j'en ai assez pour aujourd'hui!)

harrymc
la source
Je pense que cela fonctionnera très bien. Laissez-moi bricoler et je vous
répondrai
1
Cela fonctionne pour les lecteurs. Comment puis-je modifier cela pour détecter tout périphérique USB inséré, et pas seulement les lecteurs?
GiantDuck
EventType 2 détectera toute arrivée de périphérique. Pour obtenir les détails, il faudra creuser davantage l'événement. Le plus simple pourrait être d'imprimer les membres des $newEvent.SourceEventArgs.NewEventévénements qui vous intéressent.
harrymc
Ravi de voir une réponse prometteuse après presque 4 ans :) Merci beaucoup, GiantDuck & harrymc.
gemisigo
@harrymc Pouvez-vous fournir un contexte pour cela? Je n'ai jamais utilisé de PowerShell auparavant. Merci!
GiantDuck
6

Comme je l'ai déjà expliqué dans cette discussion (mais il s'agissait d'exécuter un programme lorsqu'un lecteur USB est retiré), USB Safely Remove , bien qu'il ne soit pas gratuit, peut exécuter un programme lorsque certains événements concernant des périphériques USB sont déclenchés:

Une autre fonctionnalité USB Safely Remove qui le distingue des logiciels similaires démarre toutes les applications non seulement après avoir connecté un appareil , mais aussi avant de le supprimer. La fonction d'exécution automatique vous permet de configurer la sauvegarde des données avant de déconnecter un disque dur amovible, d'exécuter Total Commander avec le contenu de la clé USB, de démonter automatiquement un lecteur TrueCrypt chiffré avant de déconnecter le support USB, etc.

entrez la description de l'image ici

Bien sûr, cela ne répond pas complètement à la question, car il ne s'agit pas d'utiliser des tâches planifiées, mais l'objectif est le même, je pense, qui est d'exécuter un programme spécifique lorsqu'une clé USB est branchée.

Snark
la source
Merci beaucoup, c'est une bonne solution de contournement. Je l'ai essayé, mais malgré son bon fonctionnement, j'essaie toujours d'atteindre mon objectif initial (c'est-à-dire d'utiliser une solution disponible et gratuite en natif). Jusqu'à présent, j'ai compris qu'en utilisant les événements ID d'événement 2006 de DriverFrameworks-UserMode, je peux déclencher l'action. Ce n'est pas encore parfait cependant. Les informations nécessaires sont disponibles dans les détails de l'événement, mais je ne peux pas les filtrer pour un lecteur USB spécifique, donc le branchement d'un lecteur USB entraînera le déclenchement du déclencheur.
gemisigo
5

Cela devrait être assez simple en utilisant EventVwr.

  1. Trouvez l'événement que vous voulez - Lorsque j'ai branché un périphérique de stockage de masse USB, il a déclenché les événements suivants (sous la catégorie d'application): 20001, 20003, 7036 et quelques autres moins pertinents. Assurez-vous de tester ces événements par rapport à d'autres événements de périphériques USB pour éviter les faux positifs.

  2. faites un clic droit sur l'événement et cliquez sur "Attacher la tâche à cet événement" (pertinent uniquement dans Windows Vista ou supérieur - pour XP, il y a CLI EventTrigger), choisissez "Démarrer un programme" et pointez-le sur le script que vous souhaitez exécuter.

  3. Pour passer au script les paramètres d'événement dont vous avez besoin, consultez cet article . Sous les événements 20001 et 20003, vous pouvez trouver le chemin UNC vers le nouveau stockage. À l'aide de l'utilitaire Sysinternals Junction, vous pouvez créer des liens vers les chemins UNC.

EliadTech
la source
J'aime l'idée de cela, mais elle n'est pas assez détaillée; Je n'arrive pas à le faire marcher.
GiantDuck
@GiantDuck Pour moi, cela semble assez simple, sur quoi aimeriez-vous que j'élabore?
EliadTech
Je ne trouve pas ces événements dans l'Observateur d'événements. (Sur Win8 pour le moment) Quel est le chemin exact? Merci!
GiantDuck
J'ai écrit, c'est sous le journal «application» avec les numéros d'événement mentionnés ci-dessus. Mais j'ai testé cela sur Win7, donc peut-être que sur Win8 les numéros d'événement sont différents. Comme je l'ai dit, vous devrez quand même faire des tests pour vous assurer qu'il fonctionnera avec n'importe quel appareil que vous branchez.
EliadTech
1
Dans Win10, rien n'apparaissait dans la catégorie Application. Je devais aller au système et attacher à l'ID d'événement 98. C'est très bien pour moi car je n'aurai jamais qu'un seul appareil, mais d'autres peuvent ne pas fonctionner
dbinott
2

J'ai pu faire fonctionner cela: j'ai trouvé l'événement 1003 dans les journaux des applications et des services, Microsoft-Windows-DriverFrameworks-UserMode pour un téléphone branché sur USB

Xml complet de l'événement:

- <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
- <System>
  <Provider Name="Microsoft-Windows-DriverFrameworks-UserMode" Guid="{2E35AAEB-857F-4BEB-A418-2E6C0E54D988}" /> 
  <EventID>1003</EventID> 
  <Version>1</Version> 
  <Level>4</Level> 
  <Task>17</Task> 
  <Opcode>1</Opcode> 
  <Keywords>0x8000000000000000</Keywords> 
  <TimeCreated SystemTime="2016-08-19T01:42:06.292278900Z" /> 
  <EventRecordID>17516</EventRecordID> 
  <Correlation /> 
  <Execution ProcessID="456" ThreadID="2932" /> 
  <Channel>Microsoft-Windows-DriverFrameworks-UserMode/Operational</Channel> 
  <Computer>5CG6070VFK-W7.nikonprecision.com</Computer> 
  <Security UserID="S-1-5-18" /> 
  </System>
- <UserData>
- <UMDFDriverManagerHostCreateStart lifetime="{AFEC92AD-6015-4AB4-86AE-F34CEE06A977}" xmlns:auto-ns2="http://schemas.microsoft.com/win/2004/08/events" xmlns="http://www.microsoft.com/DriverFrameworks/UserMode/Event">
  <HostGuid>{193a1820-d9ac-4997-8c55-be817523f6aa}</HostGuid> 
  <DeviceInstanceId>USB.VID_04E8&PID_6860&MS_COMP_MTP&SAMSUNG_ANDROID.6&3400EB54&1&0000</DeviceInstanceId> 
  </UMDFDriverManagerHostCreateStart>
  </UserData>
  </Event>

Et le filtre d'événement personnalisé pour ma tâche:

<QueryList>
  <Query Id="0" Path="Microsoft-Windows-DriverFrameworks-UserMode/Operational">
    <Select Path="Microsoft-Windows-DriverFrameworks-UserMode/Operational">*[System[Provider[@Name='Microsoft-Windows-DriverFrameworks-UserMode'] and EventID=1003]] and *[UserData[UMDFDriverManagerHostCreateStart[DeviceInstanceId="USB.VID_04E8&amp;PID_6860&amp;MS_COMP_MTP&amp;SAMSUNG_ANDROID.6&amp;3400EB54&amp;1&amp;0000"]]]</Select>
  </Query>
</QueryList>

De même pour un lecteur USB, c'était l'événement 2100, 2101, 2105, 2106
Pour un lecteur USB spécifique:

- <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
- <System>
  <Provider Name="Microsoft-Windows-DriverFrameworks-UserMode" Guid="{2E35AAEB-857F-4BEB-A418-2E6C0E54D988}" /> 
  <EventID>2101</EventID> 
  <Version>1</Version> 
  <Level>4</Level> 
  <Task>37</Task> 
  <Opcode>2</Opcode> 
  <Keywords>0x8000000000000000</Keywords> 
  <TimeCreated SystemTime="2016-08-19T01:52:37.922289600Z" /> 
  <EventRecordID>17662</EventRecordID> 
  <Correlation /> 
  <Execution ProcessID="10956" ThreadID="11892" /> 
  <Channel>Microsoft-Windows-DriverFrameworks-UserMode/Operational</Channel> 
  <Computer>5CG6070VFK-W7.nikonprecision.com</Computer> 
  <Security UserID="S-1-5-19" /> 
  </System>
- <UserData>
- <UMDFHostDeviceRequest instance="WPDBUSENUMROOT\UMB\2&37C186B&0&STORAGE#VOLUME#_??_USBSTOR#DISK&VEN_SANDISK&PROD_SANDISK_CRUZER&REV_8.02#0774230A28933B7E&0#" lifetime="{4493DBFB-81E8-4277-933D-955C4DDDD482}" xmlns:auto-ns2="http://schemas.microsoft.com/win/2004/08/events" xmlns="http://www.microsoft.com/DriverFrameworks/UserMode/Event">
- <Request major="27" minor="20">
  <Argument>0x0</Argument> 
  <Argument>0x141b</Argument> 
  <Argument>0x0</Argument> 
  <Argument>0x0</Argument> 
  </Request>
  <Status>0</Status> 
  </UMDFHostDeviceRequest>
  </UserData>
  </Event>

Il semble que l'événement 2101 se produise 3 fois avec des "<request>"balises légèrement différentes lorsque je branche mon lecteur USB:

<Request major="27" minor="20">
<Request major="27" minor="9">
<Request major="27" minor="0">

Je n'ai aucune idée de ce que cela signifie, mais voici un filtre pour un seul d'entre eux pour éviter plusieurs déclencheurs: (cela ne se déclenchera que pour ce lecteur USB spécifique)

<QueryList>
  <Query Id="0" Path="Microsoft-Windows-DriverFrameworks-UserMode/Operational">
    <Select Path="Microsoft-Windows-DriverFrameworks-UserMode/Operational">*[System[Provider[@Name='Microsoft-Windows-DriverFrameworks-UserMode'] and  EventID=2101]] and *[UserData[UMDFHostDeviceRequest[@instance="WPDBUSENUMROOT\UMB\2&amp;37C186B&amp;0&amp;STORAGE#VOLUME#_??_USBSTOR#DISK&amp;VEN_SANDISK&amp;PROD_SANDISK_CRUZER&amp;REV_8.02#0774230A28933B7E&amp;0#" and Request[@major="27" and @minor="20"]]]]</Select>
  </Query>
</QueryList>

Notez que les esperluettes doivent être échappées comme &amp;

vêtement
la source
1

Comme d'autres l'ont mentionné, il semble que l'événement du journal système 7036 du Gestionnaire de contrôle des services est le seul événement qui soit en corrélation fiable avec un lecteur USB inséré. J'ai vérifié cela en insérant un lecteur USB et en exécutant la commande powershell suivante pour répertorier toutes les entrées du journal des événements de toutes les sources au cours de la dernière heure:

get-winevent | where {$_.timecreated -ge (get-date) - (new-timespan -hour 1)}

Malheureusement, cet événement 7036 est généré à chaque fois que le Gestionnaire de contrôle des services démarre ou arrête un service, un filtrage supplémentaire est donc nécessaire.

Le filtrage disponible dans l'interface graphique de l'Observateur d'événements / Planificateur de tâches est assez basique et ne permet aucun filtrage sur les données d'événement - il vous permet uniquement de filtrer sur les métadonnées qui, dans ce cas, ne vous disent rien sur le service qui a état changé et dans quel état il a changé. Cela se trouve dans "param1" et "param2" de EventData. Le filtre XPath suivant peut donc être utilisé pour capturer uniquement le démarrage du service concerné:

<QueryList>
  <Query Id="0" Path="System">
    <Select Path="System">*[System[Provider[@Name='Service Control Manager'] and (Level=4 or Level=0) and (band(Keywords,36028797018963968)) and (EventID=7036)]]
and
*[EventData[
  Data[@Name="param1"]="Portable Device Enumerator Service" and
  Data[@Name="param2"]="running"
  ]
]
</Select>
  </Query>
</QueryList>

De là, vous pouvez exécuter votre script, idéalement avec une logique supplémentaire en place pour vérifier que la clé USB qui a été insérée est celle qui vous intéresse.

sahmeepee
la source
0

J'ai trouvé un meilleur événement (IMO) dans le journal des événements situé sous Journaux des applications et des services-Microsoft-Windows-Ntfs_Operational. Eventid 4. Il ressemble à ceci:

ID d'événement 4 Le volume NTFS a été correctement monté.

       Volume GUID: {55bf0ee3-d507-4031-a60a-22e5892ebf37}
       Volume Name: E:
       Volume Label: AirGapDrive A
       Device Name: \Device\HarddiskVolume51

À partir de cela, vous pouvez créer un déclencheur de tâche planifié et filtrer par nom de volume et / ou étiquette. Cet événement a été trouvé sur une boîte Windows Server 2019, mais pour une raison quelconque, je ne le vois pas sur mon bureau Windows 10 (1809). Peut être un événement serveur uniquement ....

RyanG
la source