題 通過檢測USB設備的連接來啟動計劃任務


我知道已經討論過,由於Win 7中自動運行(或自動播放)的限制,無法在連接時從USB驅動器啟動應用程序。但是可以創建具有事件類型觸發器的計劃任務。當驅動器 - 或任何USB設備 - 連接時,肯定會發生事件。

有沒有人知道我應該使用哪個事件ID?或者至少是什麼類型的事件?我在哪裡可以在事件查看器中找到該事件?


21
2017-12-07 14:49


起源




答案:


線程 任務計劃程序:如何自動同步我的USB閃存盤? 有一個名為monotone的用戶得到了這個答案,它與PowerShell一起使用 任務計劃程序:

我和你有同樣的問題,並與之合作   powershell(windows內置腳本)使用的技術   腳本專家博客 這裡 和 這裡。該腳本運行   作為後台進程,您可以從系統開始   使用任務計劃程序登錄。每當有新腳本時,腳本都會收到通知   驅動器已插入,然後執行某些操作(此處配置腳本   而不是任務)。因為它在等待時基本上暫停了   下一個插入的驅動器,你不應該發現它需要很多   資源。我來啦:

1)啟動Powershell ISE,可以在下面的開始菜單中找到   配件/ Windows Powershell。 2)將以下內容複製粘貼到   電源外殼:

#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')

名為'Mirror'的usb硬盤被設置為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)Voilà!

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”過程。

唯一的缺點是,啟動計算機時不會運行任何內容   已經插入驅動器。(腳本可以更改為   最初進行第一次檢查,但我已經受夠了   今天!)


12
2017-11-26 18:41



我認為這會很棒。讓我修補它,我會回复你 - GiantDuck
它適用於驅動器。如何修改此功能以進行檢測 任何 插入USB設備,而不僅僅是驅動器? - GiantDuck
EventType 2將檢測任何設備到達。獲取細節將需要更多的挖掘事件。最簡單的可能是打印成員 $newEvent.SourceEventArgs.NewEvent 對於您感興趣的活動。 - harrymc
很高興看到近4年後有希望的答案:)非常感謝,GiantDuck&harrymc。 - gemisigo
@harrymc你能為此提供一些背景嗎?我以前從未使用過powershell。謝謝! - GiantDuck


正如我已經解釋過的那樣 這個討論(但它是關於移除USB驅動器時運行程序), USB安全刪除雖然不是免費的,但可以在觸發有關USB設備的某些事件時運行程序:

另一個USB安全刪除功能   區別於類似的軟件   是 不僅開始任何應用程序   連接設備後, 但是也   在刪除之前。自動運行   功能允許您設置數據   在斷開連接之前備份   可移動硬盤,運行Total   指揮官的內容   筆式驅動器,自動卸載   之前加密的TrueCrypt驅動器   斷開USB媒體等

enter image description here

當然,這並沒有完全回答這個問題,因為它不是關於使用預定任務,但我認為目標是相同的,即在插入USB棒時運行特定程序。


6
2018-05-25 12:09



非常感謝,一個很好的解決方法,它是。我已經嘗試了但是儘管它正常工作,我仍然在努力實現我的原始目標(即使用本機可用且免費的解決方案)。到目前為止,我已經發現使用來自DriverFrameworks-UserMode的Event ID 2006事件我可以觸發操作。但它仍然不完美。事件詳細信息中提供了必要的信息,但我無法針對特定的USB驅動器進行過濾,因此插入任何USB驅動器都會導致觸發器觸發。 - gemisigo


使用EventVwr應該很容易。

  1. 找到您想要的事件 - 當我插入USB大容量存儲設備時,它觸發了以下事件(在應用程序類別下):20001,20003,7036和其他一些不太相關的事件。 確保您針對其他USB設備事件測試這些事件,以避免誤報。

  2. 右鍵單擊該事件,然後單擊“將任務附加到此事件”(僅在Windows Vista或更高版本中相關 - 對於XP有CLI EventTrigger),選擇“啟動程序”並將其指向要運行的腳本。

  3. 要將您需要的事件參數傳遞給腳本,請查看 本文。 在事件20001和20003下,您可以找到新存儲的UNC路徑。 使用Sysinternals Junction實用程序,您可以創建指向UNC路徑的鏈接。


5
2017-10-14 13:46



我喜歡這個想法,但它不夠詳細;我無法讓它發揮作用。 - GiantDuck
@GiantDuck對我來說,它看起來非常直截了當,你希望我詳細說明一下? - EliadTech
我無法在事件查看器中找到所述事件。 (目前在Win8上)確切的路徑是什麼?謝謝! - GiantDuck
我寫道,它在“應用程序”日誌下,帶有上面提到的事件編號。但是我在Win7上測試了這個,所以也許在Win8上,事件編號是不同的。正如我所說,無論如何你都需要進行一些測試,以確保它可以與你正在插入的任何設備一起使用。 - EliadTech
在Win10中沒有出現在應用程序類別中。我不得不去系統並附加到事件ID 98.這對我來說很好,因為我只會擁有那個設備,但其他設備可能無法正常工作 - dbinott


我能夠讓這個工作: 我在應用程序和服務日誌中找到了事件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>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>

我的任務的自定義事件過濾器:

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

看起來事件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;


2
2017-08-19 02:05





正如其他人所提到的,似乎來自服務控制管理器的系統日誌事件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驅動器是你感興趣的。


1
2017-11-02 14:00