問(wèn):
您好,腳本專家!我知道,在運(yùn)行腳本時(shí),可使用代碼確定腳本是否在 WScript 或 CScript 中運(yùn)行。但我想不明白的是:運(yùn)行腳本之前,如何確定計(jì)算機(jī)上的默認(rèn)腳本宿主?
-- AT
答:
您好,AT。您知道,人們完全難倒腳本專家并不是常事;不過(guò)我們不得不承認(rèn)這個(gè)問(wèn)題的確有點(diǎn)挑戰(zhàn)性。(嗯,嗯:那么,或許它并不足以能夠難倒腳本專家;老實(shí)說(shuō),事實(shí)上它相當(dāng)簡(jiǎn)單。不過(guò)你們無(wú)需知道這些。)我們還不知道如何回答這個(gè)問(wèn)題,但我們知道,為了幫助您解決這個(gè)問(wèn)題,我們將會(huì)需要大量辛勤的工作和奉獻(xiàn)。
但是,在困難面前,腳本專家放棄過(guò)嗎?嗯,事實(shí)上,我們放棄過(guò)。不過(guò),在處理一些毫不相關(guān)的事情時(shí),我們卻意外發(fā)現(xiàn)了答案。以下這個(gè)腳本(使用有點(diǎn)迂回的方法)將告訴您計(jì)算機(jī)上的默認(rèn)腳本宿主:
復(fù)制代碼 代碼如下:
Const HKEY_CLASSES_ROOT = H80000000
strComputer = "."
Set objRegistry = GetObject("winmgmts:\\" strComputer "\root\default:StdRegProv")
strKeyPath = "VBSFile\Shell\Open\Command"
objRegistry.GetExpandedStringValue HKEY_CLASSES_ROOT,strKeyPath,vbNullString,strValue
strValue = LCase(strValue)
If InStr(strValue, "wscript.exe") then
Wscript.Echo "WScript"
Else
Wscript.Echo "CScript"
End If
從中可以看出,有關(guān)默認(rèn)腳本宿主的信息存儲(chǔ)在注冊(cè)表中,盡管不是處在特別明顯的位置。您所需要做的只是打開(kāi) HKEY_CLASSES_ROOT,找到注冊(cè)表項(xiàng) VBSFile\Shell\Open\Command,然后查看默認(rèn)值。(默認(rèn)值是個(gè)例外的未命名的注冊(cè)表值,該注冊(cè)表值在 Regedit 中以“(默認(rèn))”的形式出現(xiàn)。)“(默認(rèn))”的值將是腳本宿主可執(zhí)行程序的路徑 (例如,%SystemRoot%\System32\WScript.exe)。換句話說(shuō),可執(zhí)行程序文件將告訴您默認(rèn)腳本宿主是 CScript 還是 WScript。
那么,實(shí)際上我們?nèi)绾潍@得該值呢?嗯,我們首先定義一個(gè)名為 HKEY_CLASSES_ROOT 的常量,并將其值設(shè)定為 H80000000;這會(huì)告訴腳本我們要使用哪個(gè)注冊(cè)表配置單元。然后,連接到本地計(jì)算機(jī)上的 WMI 服務(wù)(盡管我們可輕而易舉地對(duì)遠(yuǎn)程計(jì)算機(jī)運(yùn)行該腳本),務(wù)必綁定到 root\default 命名空間。(大多數(shù) WMI 腳本使用 root\cimv2 命名空間,但是出于某些原因,系統(tǒng)注冊(cè)表提供程序還是位于 root\default 中。可能是住房較便宜或是學(xué)校較好的原因吧。)
進(jìn)行連接后,我們創(chuàng)建名為 strKeyPath 的變量,并為其分配值 VBSFile\Shell\Open\Command。此時(shí),我們準(zhǔn)備從注冊(cè)表中讀取該值。
什么?難道我們忘了什么事情?不,我們未忘記任何事情。(盡管現(xiàn)在您提到它,但我們卻有點(diǎn)想知道在我們?cè)缟想x開(kāi)屋子的時(shí)候是否有人將爐子關(guān)閉。)您說(shuō)對(duì)了,在大多數(shù) WMI 注冊(cè)表腳本中,我們需要將值分配給兩個(gè)變量,一個(gè)代表注冊(cè)表項(xiàng),另一個(gè)代表注冊(cè)表項(xiàng)中所需的值。不過(guò),在本例中,我們不需要?jiǎng)?chuàng)建在其中存儲(chǔ)注冊(cè)表值名稱的變量。為什么不能呢?因?yàn)?,從技術(shù)角度來(lái)說(shuō),“(默認(rèn))”值實(shí)際上并沒(méi)有名稱;它們只不過(guò)是默認(rèn)值而已。我們最終所要做的是告訴該腳本從此特殊的注冊(cè)表項(xiàng)中讀取 Null 值。這聽(tīng)起來(lái)似乎不是很好的計(jì)劃,不過(guò)幸運(yùn)的是,“注冊(cè)表提供程序”將知道這意味著讀取“(默認(rèn))”值。
事實(shí)上,當(dāng)談到這個(gè)主題時(shí),以下該行代碼便可為我們檢索值:
objRegistry.GetExpandedStringValue HKEY_CLASSES_ROOT,strKeyPath,vbNullString,strValue
因?yàn)椤?默認(rèn))”碰巧具有 REG_EXPAND_SZ 數(shù)據(jù)類型,所以我們調(diào)用 GetExpandedStringValue 方法,傳遞四個(gè)參數(shù):
? HKEY_CLASSES_ROOT,告訴腳本要使用哪個(gè)注冊(cè)表配置單元的常量。
? strKeyPath,告訴腳本要使用哪個(gè)注冊(cè)表項(xiàng)的變量。
? vbNullString,一個(gè)代表 Null 值的 VBScript 常量。這是我們通常插入代表值名稱變量之處,不過(guò)正如我們說(shuō)過(guò)的,這次我們的值沒(méi)有名稱。
? strValue,一個(gè)“輸出”參數(shù)。GetExpandedStringValue 需要用一個(gè)地方來(lái)存儲(chǔ)其從注冊(cè)表中讀取的值;輸出參數(shù)只是一個(gè)占位符變量,可在其中存儲(chǔ)值。
GetExpandedStringValue 可用后,我們便可使用該行代碼將 strValue 中的所有字符更改為小寫(xiě);這樣做是為了更容易確定該值是否含有特殊字符串。
strValue = LCase(strValue)
最后,我們調(diào)用 InStr 函數(shù),看看是否可在 strValue 中任何地方找到該字符串值 wscript.exe。如果可以找到,則我們將回顯默認(rèn)腳本宿主 WScript;如果沒(méi)有找到,則一定意味著默認(rèn)腳本宿主為 CScript:
復(fù)制代碼 代碼如下:
If InStr(strValue, "wscript.exe") then
Wscript.Echo "WScript"
Else
Wscript.Echo "CScript"
End If
這樣就可以了,AT:現(xiàn)在,在不運(yùn)行腳本的情況下,您便可確定計(jì)算機(jī)上的默認(rèn)腳本宿主。(是的,我們知道您不得不運(yùn)行確定默認(rèn)腳本宿主的腳本…不過(guò)您找到答案了。)我們希望您能發(fā)現(xiàn)此腳本的用處,并希望每個(gè)人在今天都學(xué)到了重要一課:盡你所能,也無(wú)法難倒腳本專家。
嗯,除非您問(wèn)我們一個(gè)無(wú)法回答的問(wèn)題。但是,只要問(wèn)我們可以回答的問(wèn)題就絕不會(huì)難倒我們。
是的:幾乎沒(méi)有可能。