Scripting Guy 為您解答問題

Hey, Scripting Guy!

歡迎使用 TechNet 專欄,Microsoft Scripting Guy 會在此為您解答有關系統管理指令碼的常見問題。您有關於系統管理指令碼方面的問題嗎?請將電子郵件傳送到 scripter@microsoft.com。我們無法保證能夠逐一回答每個問題,不過我們會盡力而為。

資源

如何判斷安裝在電腦上的 QuickTime 是哪一種版本?

Hey, Scripting Guy! Question

嗨,Scripting Guy!如何判斷電腦是否有安裝 QuickTime?如果有,安裝的是哪一種版本?

        -- IU

Hey, Scripting Guy! Answer

IU,您好。您知道嗎?基於某些原因,這個專欄似乎突然變成每日舞蹈專欄而非每日指令碼專欄。畢竟,就在昨天 (英文),我們概述了 Scripting Son 在他親戚婚禮上的...跳舞...事蹟。今天,當撰寫本專欄的 Scripting Guy 正在泡咖啡時,他注意到一則探戈舞課程的廣告。該廣告說,學習如何跳探戈,您就能夠在「任何大城市跳舞 -- 而且不需攜帶舞伴!」

我們必須承認,這點一開始聽起來很好,而且我們都準備要報名了。但是,隨後我們發現一點:Scripting Guy 根本就不需要探戈舞課程。前往任何大城市,而且不用找到願意跟您跳舞的人?這點對於 Scripting Guy 而言並不是什麼問題。我們不需要有關如何讓別人不想與我們一起做任何事的課程。

除此之外,我們對於這整個探戈舞課程有點懷疑。撰寫本專欄的 Scripting Guy 常常被告知「一定要兩個人才能跳探戈」。而廣告卻告訴他不需要任何舞伴,顯然只要一個人就能跳探戈。如果沒有親眼見識,真的無法相信。

但是我們希望永遠不會看見任何 Scripting Guy 跳探戈。

真的不希望,甚至是 Peter 也一樣。事實上,尤其是 Peter。

從另一方面來講,我們想要看見的就是 IU 想要看見的同一件事:可告訴您電腦是否有安裝 QuickTime 的指令碼。其實,就是類似下面內容的指令碼:

Script Center
strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colItems = objWMIService.ExecQuery _
    ("Select * From Win32_Product Where Name = 'QuickTime'")

If colItems.Count = 0 Then
    Wscript.Echo "QuickTime is not installed on this computer."
Else
    For Each objItem in colItems
        Wscript.Echo "QuickTime version: " & objItem.Version
    Next
End If

如您所見,判斷電腦是否有安裝 QuickTime 甚至比跳探戈要簡單 (至少我們假設如此,因為我們從未真的跳過探戈)。如您所見,我們一開始要連線到本機電腦上的 WMI 服務。不過,如同大部分 WMI 指令碼,我們也可以使用這個指令碼來判斷遠端電腦是否已安裝 QuickTime。究竟該怎麼做?很簡單。只要將遠端電腦的名稱 (例如,atl-ws-01) 指派給變數 strComputer 即可:

strComputer = "atl-ws-01"

完成連線之後,我們接著要使用下面這行程式碼來擷取 Name 含有 QuickTime 值的所有已安裝軟體清單:

Set colItems = objWMIService.ExecQuery _
    ("Select * From Win32_Product Where Name = 'QuickTime'")

如同之前說過,這個指令碼會傳回一個集合,其中包含安裝在電腦上而且具有 QuickTime 名稱的每個應用程式。然後,假設我們沒有真正安裝 QuickTime。沒關係。在此情況下,我們只會取得含有 0 個項目的集合而已。如此一來,這表示我們可以透過檢查傳回集合中的項目數 (檢查集合的 Count 屬性值),識別是否有安裝 QuickTime:

If colItems.Count = 0 Then

如果 Count 等於 0,就表示沒有安裝 QuickTime。因此,我們要回應該結果的訊息:

Wscript.Echo "QuickTime is not installed on this computer."

同理,這也表示,如果 Count 大於 0,就必定安裝了 QuickTime。在此情況下,我們要設定一個 For Each 迴圈來逐一執行集合中的所有項目,而且針對每個項目,回應 Version 屬性的值:

For Each objItem in colItems
    Wscript.Echo "QuickTime version: " & objItem.Version
Next

接著就得出類似下面所示的值:

7.1.5.120

至此您已經找到答案:利用這個值,您可以取得電腦上已安裝的 QuickTime 版本,而且皆大歡喜。

但是,執行 Windows Server 2003 的人可能就不太高興了。根據預設,Windows 2003 並沒有安裝 Win32_Product 類別。除非您事先新增了這個類別 (可透過 [新增或移除程式] 完成),否則這個指令碼對您沒有任何作用。但是,其他人還是皆大歡喜。

不過,執行 Windows Vista 的人可能也不太高興了。其實,Windows Vista 預設安裝 Win32_Product 類別,甚至以某些其他屬性強化此類別。但是,Windows Vista 上的 Win32_Product 類別有一些已知問題:有時候它完全無法運作 (傳回錯誤),而且有時候雖然它會運作,但是執行速度可能比您期望 (或想要) 的速度還慢。例如,告訴我們是否已安裝 QuickTime 的這一小段指令碼可能需要一分鐘 (甚至更久) 才能完成。

如果這樣值得安慰,我們也會同意。

那麼,是否有其他方式可判斷電腦是否有安裝 QuickTime?如果有,安裝的是哪一種版本?事實上,我們知道許多解決方法。例如,如果您在登入指令碼中執行這項檢查,就可以改用下面這一小段指令碼:

On Error Resume Next

Set objQuickTime = CreateObject("QuickTimeCheckObject.QuickTimeCheck.1")

If Err <> 0 Then
    Wscript.Echo "QuickTime is not installed on this computer."
Else
    Wscript.Echo "QuickTime version: " & Hex(objQuickTime.QuickTimeVersion)
End If

在此,我們嘗試建立 QuickTime.QuickTimeCheck.1 物件的執行個體。如果無法建立此物件,就表示沒有安裝 QuickTime,而且我們要回應該結果的訊息。如果可以建立此物件,我們接著要抓取 Version 屬性的值、將該值轉換成十六進位數字,然後回應結果:

Wscript.Echo "QuickTime version: " & Hex(objQuickTime.QuickTimeVersion)

為什麼我們要將該值轉換成十六進位數字呢?這問倒我們了,必須如此而已。這是因為 Version 會回傳成類似 118849536 的值,所以將該值轉換成十六進位值就會產生版本號碼 7158000。這樣不是很好?沒錯。在我們的測試電腦上,剛好執行 QuickTime 7.1.5。

請注意:為什麼這個值實際上會回傳成 7.1.5.8000,而 Win32_Product 所回報的版本會回傳成 7.1.5.120 呢?我們也不知道。不過,7.1.5 是透過 QuickTime UI 所回報的正式版本號碼,所以我們不需要擔心這項差異。

但是,不幸的是,這個指令碼也有個問題:我們無法從遠端建立 QuickTime.QuickTimeCheck.1 物件 (這就是為什麼我們要加入在登入指令碼中執行這項檢查之條文的原因)。如果您需要從遠端執行這項工作,您可以改從登錄讀取該值:

HKEY_LOCAL_MACHINE = &H80000002

strComputer = "."

Set objReg = GetObject("winmgmts:\\" & strComputer & "\root\default:StdRegProv")

strKeyPath = "Software\Apple Computer, Inc.\QuickTime"
ValueName = "Version"

objReg.GetDWORDValue HKEY_LOCAL_MACHINE, strKeyPath, ValueName, dwValue

If IsNull(dwValue) Then
    Wscript.Echo "QuickTime is not installed."
Else
    Wscript.Echo "QuickTime version: " & Hex(dwValue)
End If

這段指令碼應該會在任何 Windows 版本上運作。那麼,為什麼我們不一開始就說明這個特定指令碼呢?一般而言,使用可直接從登錄讀取的指令碼時,我們會有點遲疑。畢竟,沒有人可以保證下一個 QuickTime 版本發行時,登錄路徑會維持相同。就這點而言,我們甚至無法保證這個指令碼會處理舊版 QuickTime。因此,最好是盡量讓 WMI 類別 (例如 Win32_Product) 進行所有工作,而非嘗試從登錄擷取這些值 (編輯小記:還有另一個原因嗎?在 Scripting Editor 的電腦上,UI 和 Win32_Product 回報版本 7.0.3、QuickTime.QuickTimeCheck.1 物件的檢查傳回 7038000,而登錄傳回 70 2 *8000)。*但是,就如同我們所說的,非常時期要有非常做法。而且,在此情況下,稍微非常的時期就要有稍微非常的做法。

如果這樣聽起來很像我們嘗試在問題上兜圈子,就某種程度上而言,沒錯。但是,至少這提供了一種替代方法,可讓您在遇到 Win32_Product 類別的問題時使用。而且,我們保證這是唯一您會看見 Scripting Guy 跳舞兜圈子的一次,就算他們去參加六月的 TechEd 2007 (英文) 也一樣。首先,撰寫本專欄的 Scripting Guy 不會跳舞,完畢。另一個原因是,在 Scripting Guy Jean Ross 經歷過聖地牙哥那場近乎悲劇的事件 (英文) 之後,我們都一直勸她不要做一些對她而言太難的事。我們告訴她,「先學走,然後再學跑」,所幸,這次她聽我們的話 (編輯小記:撰寫本專欄的 Scripting Guy 有可能會為 Scripting Guy 同事著想嗎?少來了。他只擔心 Scripting Guy Jean Ross 會讓丟臉而已。這種事真的有可能發生,真的)。