Запуск запланированного задания по обнаружению подключения USB-устройства

47321
gemisigo

Я знаю, что обсуждалось, что невозможно запустить приложение с USB-накопителя при подключении из-за ограничений автозапуска (или автозапуска ??) в Win 7. Но возможно создать запланированное задание с триггером типа события, Конечно, должно быть событие, которое происходит, когда диск - или любое USB-устройство, в этом отношении - подключен.

Кто-нибудь имеет малейшее представление о том, какой идентификатор события следует использовать? Или хотя бы какой тип мероприятия? Где я могу найти событие в программе просмотра событий?

21

5 ответов на вопрос

12
harrymc

The thread Task Scheduler: How to automatically synchronize my USB flash drive? has this answer by a user called monotone, which uses PowerShell together with the Task Scheduler :

I had the same question as you, and worked out something with powershell (windows built-in scripting) using techniques from the Scripting Guy Blog here and here. The script runs continuously as a background process, which you can start at system logon with task scheduler. The script will be notified whenever a new drive is plugged and then do something (here you configure the script rather than the task). Since it is basically paused while waiting for the next plugged drive, you should not find it takes up much resources. Here I go:

1) Start Powershell ISE, which can be found in your start menu under Accessories/Windows Powershell. 2) Copy paste the following into 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) You need to modify the script above to tell the script what drive to look for, and what to execute. The two lines to change are:

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

My usb hard drive named 'Mirror' is set as the Z: drive. You could just use if ($driveLabel -eq 'MyDiskLabel') if you didn't care about the letter.

start-process "Z:\sync.bat" 

Path of whatever task you want to do. In my example, I have created a batch file on my USB drive which starts 3-4 backup tasks command lines.

4) When you're done, save your script somewhere (extension .ps1), then go create a task in Task Scheduler to have your script run in background. Mine looks like this:

  • Trigger: At log on
  • Action: Start a program
  • Program/script: powershell
  • Add arguments: -ExecutionPolicy Unrestricted -File "D:\Stuff\Backup script.ps1"

5) Voilà!

6) Extra stuff:

If you want your script window to be hidden, use these arguments:

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

If you want to output the script messages into a log file (that gets overwritten everytime the script starts, i.e. at log on), use the following task action:

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

Anytime you want to end the running hidden script, you can end the "Powershell" process in Task Manager.

The only downside is that nothing will run when you boot your computer with the drive already plugged in. (The script could be changed to perform a first check initially though, but I've had enough for today!)

Я думаю, что это будет отлично работать. Позвольте мне возиться с этим, и я вернусь к вам GiantDuck 9 лет назад 0
Это работает для дисков. Как я могу изменить это, чтобы обнаружить ** любое ** вставленное USB-устройство, а не только диски? GiantDuck 9 лет назад 1
EventType 2 обнаружит любое прибытие устройства. Для получения подробностей потребуется еще немного покопаться в мероприятии. Простейшим может быть печать членов `$ newEvent.SourceEventArgs.NewEvent` для интересующих вас событий. harrymc 9 лет назад 0
Приятно видеть многообещающий ответ спустя почти 4 года :) Большое спасибо, GiantDuck & harrymc. gemisigo 9 лет назад 0
@harrymc Можете ли вы предоставить контекст для этого? Я никогда раньше не использовал PowerShell. Спасибо! GiantDuck 9 лет назад 0
В Google можно найти огромное количество материалов - запрос "Обучающее руководство по Powershell" возвращает около 863 000 результатов! Для любой функции, которую вы хотите объяснить, просто Google для "PowerShell функцию". [Powershell ISE] (http://technet.microsoft.com/en-us/library/dd315244.aspx) - это среда разработки, в которой можно легко создавать и тестировать сценарии. Powershell должен знать администратор Windows. harrymc 9 лет назад 0
Я использую `Win32_DeviceChangeEvent` сейчас. Спасибо GiantDuck 9 лет назад 0
@harrymc Проблема в том, что я не могу найти событие, когда подключаю USB-микрофон, поэтому я не могу использовать это решение. Есть ли более удобный способ сделать это с помощью планировщика задач? Я мог бы использовать идентификатор устройства или что-то в этом роде. Herman Toothrot 7 лет назад 0
6
Snark

Как я уже объяснял в этом обсуждении (но речь шла о запуске программы при извлечении USB-накопителя), USB Safely Remove, хотя и не свободная, может запускать программу при возникновении некоторых событий на USB-устройствах:

Другая функция безопасного удаления USB, которая отличает его от аналогичного программного обеспечения, запускает любые приложения не только после подключения устройства, но и перед его удалением. Функция автозапуска позволяет настроить резервное копирование данных перед отсоединением съемного жесткого диска, запустить Total Commander с содержимым перьевого диска, автоматически отключить зашифрованный диск TrueCrypt перед отключением USB-носителя и т. Д.

enter image description here

Конечно, это не полностью отвечает на вопрос, поскольку речь идет не об использовании запланированных задач, но я думаю, что цель та же, что и запуск конкретной программы при подключении USB-накопителя.

Большое спасибо, хороший обходной путь, это так. Я пробовал, но, несмотря на то, что он работает должным образом, я все еще пытаюсь достичь своей первоначальной цели (то есть, используя изначально доступное и бесплатное решение). До сих пор я выяснил, что с помощью событий Event ID 2006 из DriverFrameworks-UserMode я могу инициировать действие. Это все еще не идеально, хотя. Необходимая информация доступна в сведениях о событии, но я не могу отфильтровать ее для конкретного USB-накопителя, поэтому при подключении любого USB-накопителя срабатывает триггер. gemisigo 13 лет назад 0
5
EliadTech

It should be quite easy using EventVwr.

  1. Find the event you want - When I plugged an USB mass storage device it triggered the following events (under application category): 20001, 20003, 7036 and a few other less relevant. Make sure you test those events against other USB devices events to avoid false positives.

  2. right click on the event and click "Attach task to this event" (relevant only in Windows Vista or higher - for XP there's CLI EventTrigger), choose "Start a Program" and point it to the script you want to run.

  3. To pass to the script the event parameters you need have a look in this article. Under the events 20001 and 20003 you can find the UNC path to the new storage. Using Sysinternals Junction utility you can create a links to the UNC paths.

Мне нравится идея этого, но это не достаточно подробно; Я не могу заставить его работать. GiantDuck 9 лет назад 0
@GiantDuck Для меня это выглядит довольно просто, что бы вы хотели, чтобы я уточнил? EliadTech 9 лет назад 0
Я не могу найти указанные события в Event Viewer. (На Win8 на данный момент) Какой точный путь? Спасибо! GiantDuck 9 лет назад 0
Я написал, он находится в «журнале приложений» с номерами событий, упомянутыми выше. Но я проверял это на Win7, так что, возможно, на Win8 номера событий разные. Как я уже сказал, вам все равно нужно провести некоторое тестирование, чтобы убедиться, что оно будет работать с любым подключаемым устройством. EliadTech 9 лет назад 0
В Win10 ничего не появилось в категории приложений. Мне нужно было зайти в систему и подключиться к Event ID 98. Это нормально для меня, потому что у меня будет только одно это устройство, но другие могут не работать dbinott 8 лет назад 1
2
garbb

Мне удалось заставить это работать: я обнаружил событие 1003 в журналах приложений и служб, Microsoft-Windows-DriverFrameworks-UserMode для телефона, подключенного к USB

Полный xml мероприятия:

- <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event"> - <System> <Provider Name="Microsoft-Windows-DriverFrameworks-UserMode" Guid="" />  <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="" xmlns:auto-ns2="http://schemas.microsoft.com/win/2004/08/events" xmlns="http://www.microsoft.com/DriverFrameworks/UserMode/Event"> <HostGuid></HostGuid>  <DeviceInstanceId>USB.VID_04E8&PID_6860&MS_COMP_MTP&SAMSUNG_ANDROID.6&3400EB54&1&0000</DeviceInstanceId>  </UMDFDriverManagerHostCreateStart> </UserData> </Event> 

И пользовательский фильтр событий для моей задачи:

<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> 

Аналогично для USB-накопителя это было событие 2100, 2101, 2105, 2106.
Для конкретного USB-накопителя:

- <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event"> - <System> <Provider Name="Microsoft-Windows-DriverFrameworks-UserMode" Guid="" />  <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="" 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> 

Похоже, что событие 2101 происходит 3 раза с немного другими "<request>"тегами, когда я подключаю USB-накопитель:

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

Я понятия не имею, что это означает, но вот фильтр только для одного из них, чтобы избежать нескольких триггеров: (это будет срабатывать только для этого конкретного USB-накопителя)

<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> 

Обратите внимание, что амперсанды должны быть экранированы как &amp;

1
sahmeepee

Как уже упоминалось, кажется, что Событие 7036 системного журнала от Service Control Manager является единственным событием, которое надежно связано с подключаемым USB-накопителем. Я проверил это, вставив USB-накопитель и выполнив следующую команду powershell, чтобы получить список всех записей журнала событий из всех источников за последний час:

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

К сожалению, событие 7036 генерируется каждый раз, когда диспетчер управления службами успешно запускает или останавливает любую службу, поэтому требуется дополнительная фильтрация.

Фильтрация, доступная в графическом интерфейсе Event Viewer / Task Scheduler, довольно проста и не позволяет выполнять какую-либо фильтрацию данных события - она ​​позволяет фильтровать только метаданные, которые в этом случае ничего не говорят о том, какая служба имеет изменилось состояние и в каком состоянии оно изменилось. Это содержится в «param1» и «param2» EventData. Поэтому следующий фильтр XPath можно использовать для захвата только запуска соответствующей службы:

<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> 

Оттуда вы можете запустить свой скрипт, в идеале с некоторой дополнительной логикой, чтобы убедиться, что USB-диск, который был вставлен, является тем, который вас интересует.