31

I know it has been discussed that it is not possible to start an application from an usb drive upon connection due to limitations of autorun (or autoplay??) in Win 7. But it is possible to create a scheduled task having an event type trigger. Surely there must be an event occurring when the drive -- or any USB device, for that matter -- is connected.

Does anybody have the slightest idea which Event ID should I use? Or at least what type of event? Where can I find the event in event viewer?

1
  • Great question - covers my wanting to kick off an incremental backup simply by plugging in the removable drive, saving me from faffing around firing up a backup program as well!
    – Razzle
    Commented Jan 12 at 16:58

6 Answers 6

22
+50

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

5
  • 1
    It's working for drives. How can I modify this to detect any USB device inserted, and not only drives?
    – GiantDuck
    Commented Nov 27, 2014 at 0:20
  • EventType 2 will detect any device arrival. Getting the details will require some more digging into the event. Simplest might be to print the members of $newEvent.SourceEventArgs.NewEvent for the events you are interested in.
    – harrymc
    Commented Nov 27, 2014 at 8:14
  • @harrymc Can you provide some context for that? I've never used powershell before. Thanks!
    – GiantDuck
    Commented Nov 27, 2014 at 13:32
  • There is an enormous amount of material to be found on google - the query "Powershell tutorial" returns about 863,000 results! For any function you wish explained just google for "powershell function". Powershell ISE is a development environment in which one can easily construct and test scripts. Powershell is must-know for Windows administrators.
    – harrymc
    Commented Nov 27, 2014 at 14:46
  • @harrymc The problem is that I can't find any event when I plug in my USB microphone, so I can't use this solution. Is there a more friendly way to do this with task scheduler? I could use the device ID or something like that. Commented Jan 4, 2017 at 18:49
9

I was able to get this to work: I found event 1003 in applications and services logs, Microsoft-Windows-DriverFrameworks-UserMode for a phone plugged in to usb

Full xml of the event:

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

And the custom event filter for my task:

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

Similarly for a USB drive it was event 2100, 2101, 2105, 2106
For a specific USB Drive:

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

It looks like event 2101 happens 3 times with slightly different "<request>" tags when I plug in my usb drive:

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

I have no idea what this means but here is a filter for only one of them to avoid multiple triggers: (this will only trigger for this specific USB drive)

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

Note that the ampersands must be escaped as &amp;

1
  • 1
    this is the better approach than the accepted solution, imho. been using the powershell script mentioned above, but the task to run said script kept exiting with 0x1 and not being restarted, despite being told to do so. this event-based approach is more robust and slim since it does not rely on polling/busy waiting and an additional running program. kudos. Commented Apr 15, 2021 at 19:50
7

As I already explained on this discussion (but it was about running a program when a USB drive is removed), USB Safely Remove, although not free, can run a program when some events about USB devices are triggered:

Another USB Safely Remove feature that distinguishes it from similar software is starting any applications not only after connecting a device, but also before removing it. The autorun feature allows you to set up data backup before disconnecting a removable hard drive, to run Total Commander with the contents of the pen-drive, automatically unmount an encrypted TrueCrypt drive before disconnecting the USB media, etc.

enter image description here

Of course, this does not fully answer the question, as it is not about using scheduled tasks, but the goal is the same, I think, which is to run a specific program when a USB stick is plugged in.

1
  • Thank you very much, a good workaround, it is. I've tried it but in spite of it working properly, I'm still trying to achieve my original goal (that is, using a natively available and free solution). So far I've figured out that using Event ID 2006 events from DriverFrameworks-UserMode I can trigger the action. It's still not perfect though. The necessary info is available in the event details but I cannot filter it for a specific USB drive, so plugging in any USB drive will cause the trigger to fire.
    – gemisigo
    Commented May 26, 2011 at 10:37
6

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.

6
  • I like the idea of this, but it isn't detailed enough; I can't get it to work.
    – GiantDuck
    Commented Nov 26, 2014 at 18:29
  • @GiantDuck For me it looks pretty straight-forward, on what would you like me to elaborate?
    – EliadTech
    Commented Nov 26, 2014 at 18:44
  • I can't find said events in Event Viewer. (On Win8 at the moment) What is the exact path? Thank you!
    – GiantDuck
    Commented Nov 26, 2014 at 23:40
  • I wrote, it's under 'application' log with the event numbers mentioned above. But I've tested this on Win7, so maybe on Win8 the event numbers are different. As I said you'll need to do some testing anyway to ensure it would work with any device you're plugging.
    – EliadTech
    Commented Nov 27, 2014 at 6:40
  • 2
    In Win10 nothing appeared in Application category. I had to go to System and attach to Event ID 98. It's fine for me cause I will only ever have that one device, but others may not work
    – dbinott
    Commented May 25, 2016 at 19:20
2

As others have mentioned, it seems that System log Event 7036 from the Service Control Manager is the only event which correlates reliably with a USB drive being inserted. I checked this by inserting a USB drive and running the following powershell command to list all event log entries from all sources in the last hour:

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

Unfortunately that Event 7036 is generated every time the Service Control Manager successfully starts or stops any service, so additional filtering is required.

The filtering available in the GUI of Event Viewer / Task Scheduler is quite basic and doesn't allow for any filtering on the event data - it only lets you filter on the metadata which in this case doesn't tell you anything about which service has changed state and what state it has changed to. That is held in "param1" and "param2" of the EventData. The following XPath filter can therefore be used to capture only the relevant service starting up:

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

From there you can run your script, ideally with some additional logic in place to check that the USB drive which has been inserted is the one you are interested in.

1

I found a better (IMO) event from the event log located under Applications and Service Logs-Microsoft-Windows-Ntfs_Operational. Eventid 4. It looks like this:

Event ID 4 The NTFS volume has been successfully mounted.

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

From that you can create a scheduled task trigger and filter by volume name and or label. This event was found on a Windows Server 2019 box, however for some reason I'm not seeing it on my Windows 10 (1809) desktop. May be a server only event....

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .