通过检测 USB 设备的连接来启动计划任务

通过检测 USB 设备的连接来启动计划任务

我知道有人讨论过,由于 Win 7 中自动运行(或自动播放??)的限制,连接 USB 驱动器后无法启动应用程序。但可以创建具有事件类型触发器的计划任务。当然,当驱动器(或任何 USB 设备)连接时,一定会发生事件。

有人知道我应该使用哪个事件 ID 吗?或者至少知道是什么类型的事件?我在事件查看器中可以在哪里找到该事件?

答案1

线程任务计划程序:如何自动同步我的 USB 闪存驱动器? 有一个名为 monotone 的用户给出了这个答案,它将 PowerShell 与任务计划程序结合使用:

我和你有同样的问题,并使用脚本专家博客中的技术,用 powershell (windows 内置脚本) 解决了一些问题这里这里。脚本作为后台进程持续运行,您可以在系统登录时使用任务计划程序启动它。每当插入新驱动器时,脚本都会收到通知,然后执行某些操作(在这里您可以配置脚本而不是任务)。由于它在等待下一个插入驱动器时基本上处于暂停状态,因此您不会发现它占用太多资源。我来看一下:

1) 启动 Powershell ISE,可以在开始菜单的附件/Windows Powershell 下找到。2) 将以下内容复制粘贴到 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) 您需要修改上述脚本,告诉脚本要查找哪个驱动器以及要执行什么。需要更改的两行是:

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

我的 USB 硬盘驱动器名为“Mirror”,设置为 Z: 驱动器。if ($driveLabel -eq 'MyDiskLabel')如果您不介意字母,则可以直接使用。

start-process "Z:\sync.bat"

您要执行的任何任务的路径。在我的示例中,我在 USB 驱动器上创建了一个批处理文件,该文件启动了 3-4 个备份任务命令行。

4) 完成后,将脚本保存在某个位置(扩展名.ps1),然后在任务计划程序中创建一个任务,让脚本在后台运行。我的脚本如下所示:

  • 触发条件:登录时
  • 操作:启动程序
  • 程序/脚本:powershell
  • 添加参数:-ExecutionPolicy Unrestricted -File "D:\Stuff\Backup script.ps1"

5)瞧!

6)额外内容:

如果您希望隐藏脚本窗口,请使用以下参数:

  • 添加参数:
    -WindowStyle Hidden -ExecutionPolicy Unrestricted -File "D:\Stuff\Backup script.ps1"

如果您想要将脚本消息输出到日志文件(每次脚本启动时,即登录时,该文件都会被覆盖),请使用以下任务操作:

  • 程序/脚本:cmd
  • 添加参数:
    /c powershell -WindowStyle Hidden -ExecutionPolicy Unrestricted -File "D:\Stuff\Backup script.ps1" > "D:\Stuff\script log.txt”

任何时候您想要结束正在运行的隐藏脚本,您都可以在任务管理器中结束“Powershell”进程。

唯一的缺点是,当您在驱动器已插入的情况下启动计算机时,什么都不会运行。(虽然可以将脚本更改为最初执行第一次检查,但我今天已经受够了!)

答案2

我能够让它工作:我在应用程序和服务日志中找到了事件 1003,对于插入 USB 的手机,Microsoft-Windows-DriverFrameworks-UserMode

事件的完整 xml:

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

以及我的任务的自定义事件过滤器:

<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="{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>

"<request>"当我插入 USB 驱动器时,事件 2101 似乎发生了 3 次,且标签略有不同:

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

答案3

正如我已经解释的那样这次讨论(但这是关于在移除 USB 驱动器时运行程序)USB 安全移除虽然不是免费的,但是当触发一些有关 USB 设备的事件时,可以运行一个程序:

USB 安全删除与类似软件的另一个区别功能是不仅在连接设备后启动任何应用程序,而且在移除之前也会自动执行。自动运行功能允许您在断开可移动硬盘之前设置数据备份,使用 U 盘的内容运行 Total Commander,在断开 USB 介质之前自动卸载加密的 TrueCrypt 驱动器等。

在此处输入图片描述

当然,这并不能完全回答这个问题,因为它与使用计划任务无关,但我认为目标是相同的,即在插入 USB 记忆棒时运行特定程序。

答案4

正如其他人提到的,似乎服务控制管理器中的系统日志事件 7036 是唯一与插入 USB 驱动器可靠关联的事件。我通过插入 USB 驱动器并运行以下 powershell 命令来检查这一点,以列出过去一小时内来自所有来源的所有事件日志条目:

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

不幸的是,每次服务控制管理器成功启动或停止任何服务时都会生成事件 7036,因此需要进行额外的过滤。

事件查看器/任务计划程序的 GUI 中提供的过滤功能非常基础,不允许对事件数据进行任何过滤 - 它只允许您过滤元数据,在这种情况下,元数据不会告诉您哪个服务已更改状态以及它已更改为什么状态。这些信息保存在 EventData 的“param1”和“param2”中。因此,可以使用以下 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 驱动器是否是您感兴趣的。

相关内容