您好,腳本專家!如何確定哪些 USB 設(shè)備已連接到計算機上?
-- WM
您好,WM。您是否經(jīng)常觀看大量電視節(jié)目,而不像我們腳本專家一樣,在業(yè)余時間閱讀 Shakespeare 的著作、解答微分方程式或進行其他趨向于開發(fā)智力的活動?不過,正如有人曾經(jīng)告訴過我們的那樣,每當(dāng)電視節(jié)目中出現(xiàn)危急關(guān)頭時,一個主要人物就會抓起一個手提式擴音器大喊,試圖讓人群平靜下來。“保持安靜!”此人對人群大喊道。“沒有必要驚慌。一切都很正常。”
許多時候,我們腳本專家也希望自己能有一個擴音器,而這里就有一個。您能確定哪些 USB 設(shè)備已連接到計算機上嗎?是的,盡管看到“如何”時您可能開始有點兒驚慌,但您必須去解決這個問題。保持鎮(zhèn)靜。沒有必要驚慌。
您說的沒錯:我們應(yīng)該去演自己的電視劇,不是嗎?
我們在此面臨的問題是沒有專用于 USB 設(shè)備的動態(tài)類:您不能像使用 Win32_Services 返回計算機上所有服務(wù)的集合一樣,來返回 USB 設(shè)備的集合。您必須使用 WMI 關(guān)聯(lián)類 (Win32_USBControllerDevice),將 USB 控制器與 USB 設(shè)備相關(guān)聯(lián)。使用該信息,您可以識別關(guān)聯(lián)中的相關(guān)實體(恰好就是與 USB 控制器關(guān)聯(lián)的設(shè)備),然后可以查詢 Win32_PNPEntity 以獲得有關(guān)設(shè)備自身的信息。(遺憾的是,Win32_USBControllerDevice 除了返回有點兒模糊不清的設(shè)備 ID 之外,不會返回有關(guān)設(shè)備的任何其他信息。)
感到困惑不解嗎?別沮喪;我們還不完全確定我們已經(jīng)理解它。那么,咱們商量一下吧:我們將腳本展示給您,然后您可以自己決定是否需要解釋此腳本的工作原理:
strComputer = "."Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")Set colDevices = objWMIService.ExecQuery _("Select * From Win32_USBControllerDevice")For Each objDevice in colDevicesstrDeviceName = objDevice.DependentstrQuotes = Chr(34)strDeviceName = Replace(strDeviceName, strQuotes, "")arrDeviceNames = Split(strDeviceName, "=")strDeviceName = arrDeviceNames(1)Set colUSBDevices = objWMIService.ExecQuery _("Select * From Win32_PnPEntity Where DeviceID = ‘" & strDeviceName & "‘")For Each objUSBDevice in colUSBDevicesWscript.Echo objUSBDevice.DescriptionNextNext
噢,很好,您仍然與我們的意見一致。正如您看到的,此腳本首先對 Win32_USBControllerDevice 進行了查詢;此操作返回了所有 USB 控制器以及當(dāng)前與它們相關(guān)聯(lián)的設(shè)備的集合。這是個好消息。但還有一個壞消息:我們需要隔離集合中各個項的相應(yīng)實體,即一個表示 USB 設(shè)備的實體。為什么這是個壞消息呢?之所以這么說,是因為相應(yīng)的屬性值可能看起來與以下內(nèi)容類似:
\\TOMSERVO\root\cimv2:Win32_PnPEntity.DeviceID="USB\\VID_045E&PID_0029\\5&236EE205&0&2"
討厭!我們需要執(zhí)行的操作就是以某種方式隔離實際的設(shè)備 ID;在此例中為“USB\\VID_045E&PID_0029\\5&236EE205&0&2”。當(dāng)我們獲得該值后,就可以查詢 Win32_PNPEntity 類以獲取有關(guān)該設(shè)備的信息。
那么我們?nèi)绾胃綦x設(shè)備 ID 呢?哦,大概有無數(shù)種方法可以實現(xiàn)此目的;我們選擇一種我們認為比較容易的方法來操作吧。(此方法將給您提供一些關(guān)于其他方法是什么樣子的提示。)
首先,我們將相應(yīng)屬性的值存儲在一個名為 strDeviceName 的變量中。然后,我們使用 VBScript Replace 函數(shù)將雙引號 – 我們使用 Chr(34) 表示雙引號 – 從字符串中刪除。這樣將得到與以下類似的值:
\\TOMSERVO\root\cimv2:Win32_PnPEntity.DeviceID=USB\\VID_045E&PID_0029\\5&236EE205&0&2
信不信由您,刪除這些雙引號后就基本上大功告成了。如果仔細地檢查其余的值,您將注意到它們基本上分為兩個部分,這兩個部分被一個等號分隔開了。等號的左邊是類和屬性的 WMI 路徑,等號的右邊是設(shè)備 ID。這和我們有什么關(guān)系呢?現(xiàn)在我們可以使用 VBScript Split 函數(shù)來拆分等號上的值,然后創(chuàng)建由兩個項組成的數(shù)組。第 1 項將是 WMI 路徑,第 2 項將是 – 答對了! – 設(shè)備 ID。這兩行代碼創(chuàng)建數(shù)組,然后將數(shù)組中第 2 項的值(設(shè)備 ID)分配給變量 strDeviceName:
arrDeviceNames = Split(strDeviceName, "=")strDeviceName = arrDeviceNames(1)
現(xiàn)在我們就得到了連接到計算機的第一個 USB 設(shè)備的設(shè)備 ID。有了設(shè)備 ID,我們就可以查詢 Win32_PNPEntity 類以獲得有關(guān)分配了設(shè)備 ID 的 USB 設(shè)備的信息。這就是下面的代碼執(zhí)行的操作:
Set colUSBDevices = objWMIService.ExecQuery _("Select * From Win32_PnPEntity Where DeviceID = ‘" & strDeviceName & "‘")
這個查詢將返回有關(guān)實際設(shè)備自身的信息。在此腳本中,盡管很容易回顯所有在 Win32_PNPEntity 類中找到的屬性的值,但我們只回顯了每個設(shè)備的 Description 屬性的值。然后,為 Win32_USBControllerDevice 集合中的各個項循環(huán)并重復(fù)此過程。
運行此腳本時,我們將獲得與以下類似的信息(當(dāng)然,這取決于當(dāng)前與計算機相連的設(shè)備):
USB Root HubMicrosoft USB IntelliMouse WebMicrosoft USB IntelliMouse WebUSB Mass Storage DeviceDisk driveGeneric volumeUSB Root HubUSB Root Hub
此腳本并不完美;USB 大容量存儲設(shè)備、磁盤驅(qū)動器和通用卷均指同一個 USB keychain 驅(qū)動器。但至少它可以讓您大概了解哪些設(shè)備連接到了(或沒有連接到)計算機上。
就像我們剛才所說的:沒有必要驚慌。一切都很正常。