問: 您好,腳本專家!如何確定 USB 閃存驅動器的連接時間? -- PS 答: 您好,PS。是的,我們承認:腳本專家確實懶惰。(尤其是在周五,這一天我們必須編寫周一專欄。)可能有一種方法能夠專門監(jiān)視何時插入 USB 閃存驅動器。但是,我們找不到這種方法,至少不能馬上找到它。不可否認,或許我們可能感覺有點困難。但是,我們還是決定編寫一個腳本,用來告訴您任何可移動驅動器與計算機連接(或斷開連接)的時間。我們希望這樣可以為您提供一些附加價值和靈活性。 嗨,我們并沒有說我們確實已為您提供了附加價值和靈活性。我們只是希望自己能夠做到。 實際上,這是一個容易編寫的小腳本。另外,它還有一個優(yōu)點,就是能夠在任意版本的 Windows 上運行。(最初,我們曾經(jīng)不加思索地想要使用 Win32_VolumeChangeEvent 類來完成這項任務,但是,該特定 WMI 類只能在 Windows Server 2003 上找到。) 該段代碼如下所示:
復制代碼 代碼如下:
strComputer = "." Set objWMIService = GetObject("winmgmts:\\" strComputer "\root\cimv2") Set colEvents = objWMIService.ExecNotificationQuery _ ("Select * From __InstanceOperationEvent Within 10 Where " _ "TargetInstance isa 'Win32_LogicalDisk'") Do While True Set objEvent = colEvents.NextEvent If objEvent.TargetInstance.DriveType = 2 Then Select Case objEvent.Path_.Class Case "__InstanceCreationEvent" Wscript.Echo "Drive " objEvent.TargetInstance.DeviceId _ " has been added." Case "__InstanceDeletionEvent" Wscript.Echo "Drive " objEvent.TargetInstance.DeviceId _ " has been removed." End Select End If Loop
是的,它確實類似于幾天前我們向您展示的屏幕保護程序監(jiān)視腳本。我們希望重復使用同一個腳本為您提供附加價值和靈活性。(盡管這主要是確保我們能夠節(jié)省精力。) 此腳本首先連接到本地計算機上的 WMI 服務。然后,我們發(fā)出以下查詢: Set colEvents = objWMIService.ExecNotificationQuery _ ("Select * From __InstanceOperationEvent Within 10 Where " _ "TargetInstance ISA 'Win32_LogicalDisk'") 這個查詢起什么作用呢?嗯,這里我們要使用 ExecNotificationQuery 方法來訂閱一組特定的 WMI 事件。什么 WMI 事件?(伙計,您的問題太多了,不是嗎?)在本例中,我們希望在每次更改 Win32_LogicalDisk 類的實例時我們都會得到通知。正如您馬上就能看到的,這些更改將包括:為該類創(chuàng)建一個新實例(即,添加一個可移動驅動器)和刪除該類的一個現(xiàn)有實例(即,取下一個可移動驅動器)。Within 10 只是意味著每 10 秒鐘我們將檢查一次,看看是否有任何 Win32_LogicalDisk 實例發(fā)生了變化。 是的,這也意味著,如果您插入了一個可移動驅動器,然后在 6 秒鐘后將其取出,那么我們可能永遠也不會知道這件事。如果這是個問題,那么將 10 改為一個更小的數(shù)值。也可以將 10 改為一個更大的數(shù)值。例如,將 10 改為 60,就會每 60 秒鐘進行一次檢查,而不是每 10 秒鐘。 明白了嗎?我們甚至將附加價值和靈活性加入了代碼自身中! 然后,我們建立一個不停運行的 Do 循環(huán):: Do While True 接下來我們遇到了下面這行代碼: Set objEvent = colEvents.NextEvent 正如我們在上一專欄中說過的,這行代碼將使腳本“中斷”,意思就是腳本將暫停在此行,直到 Win32_LogicalDisk 類發(fā)生變化為止。這種變化(可以是創(chuàng)建了新實例或者是刪除/修改了一個現(xiàn)有實例)將使腳本執(zhí)行 Do 循環(huán)中的其余代碼行。 好問題:剩下那些行代碼究竟要做什么?嗯,首先看一下生成事件的驅動器是否恰好為可移動驅動器(至少就 WMI 而言,DriveType 為 2): If objEvent.TargetInstance.DriveType = 2 Then 如果 DriveType 不是 2,那么我們只能再循環(huán)并等待下一個事件的發(fā)生。如果 DriveType 等于 2,那么我們使用 Select Case 塊來確定發(fā)生的是哪種類型的事件。我們可通過確定事件的 Class 來執(zhí)行此操作: Select Case objEvent.Path_.Class 為什么這樣做?有兩個原因:首先,我們并不關心現(xiàn)有實例所發(fā)生的任何變化。例如,我們并不關心驅動器 C 上的可用驅動器空間是否發(fā)生了變化。如果您看一下 Select Case 代碼,您就會注意到我們并不去費神檢查 __InstanceModificationEvent。為什么不呢?因為我們并不關心 __InstanceModificationEvent(以某種方式修改現(xiàn)有實例時生成的事件的類型)。 其次,我們想要對 __InstanceCreationEvent(它會告訴我們已經(jīng)創(chuàng)建了一個新驅動器)和 __InstanceDeletionEvent(它會告訴我們已經(jīng)刪除了一個現(xiàn)有驅動器)加以區(qū)別。通過確定事件類型,我們可以回顯不同(并相應)的消息。例如,下面是用于確定是否創(chuàng)建了新驅動器的代碼,如果是,則回顯一條用于指示該結果的消息: Case "__InstanceCreationEvent" Wscript.Echo "Drive " objEvent.TargetInstance.DeviceId _ " has been added." 下面是用于通知我們是否刪除了現(xiàn)有驅動器的代碼: Case "__InstanceDeletionEvent" Wscript.Echo "Drive " objEvent.TargetInstance.DeviceId _ " has been removed." 回顯相應的消息后,我們再循環(huán)并等待下一個事件的發(fā)生。默認情況下,該腳本將永遠運行下去,或者至少在您終止該腳本進程之前會是這樣。先發(fā)生哪種情況就先執(zhí)行哪段代碼。 正如我們說過的,這并不是您真正想要的,但是它確實能夠達到這一目的。哦,不要忘了附加價值和靈活性。這應該足以彌補一個事實,那就是我們并沒有真正回答您的問題。(我們希望我們已經(jīng)解答了該問題的一個方面。不過這不是您的問題。)