嗨,Scripting Guy!

嗨,Scripting Guy!

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

還有,別忘了瞧瞧全新經過改良的《嗨,Scripting Guy!過往文件》。

今天的問題:如何監視登錄機碼的變更呢?


如何監視登錄機碼的變更呢?

嗨,Scripting Guy! 我可以使用指令碼來監視登錄機碼的變更嗎?我希望只要有人變更 HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run 機碼,就隨時通知我。

-- SB

SB,您好。謝謝您費心描述問題:若要隨時接獲有人更改機碼的通知,其實很容易。不過如果您繼續問:「能不能也順便告訴我,是誰變更機碼,他又做了哪些變更?」,這就有點困難了 (容我待會兒為您解釋)。既然您沒有繼續問,就當我沒說吧。

我們先看看監視 HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run 登錄機碼的指令碼,然後在機碼變更時回應訊息:

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\default")
Set colEvents = objWMIService.ExecNotificationQuery _
    ("SELECT * FROM RegistryKeyChangeEvent WHERE Hive='HKEY_LOCAL_MACHINE' AND " & _
        "KeyPath='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run'") 
 
Do
    Set objLatestEvent = colEvents.NextEvent
    Wscript.Echo Now & ": The registry has been modified."
Loop

我們先連接到 WMI 服務。說得更明確一點,就是連接到 root\default 命名空間,也就是登錄事件類別所在的地方。接著再使用 ExecNotificationQuery 方法,發出下述查詢:

("SELECT * FROM RegistryKeyChangeEvent WHERE Hive='HKEY_LOCAL_MACHINE' AND " & _
        "KeyPath='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run'")

您只需要求 RegistryKeyChangeEvent 類別一建立執行個體,就發出通知。因為正如您所猜測,只要指定的登錄機碼一變更 (例如,加入新值,或是修改或刪除現有的值),這個類別就會建立一個執行個體。

聽起來很不錯,不過我們該如何指定登錄機碼呢?很簡單,只要設定 RegistryKeyChangeEvent 類別的下列兩個屬性就好:

  • Hive。這是機碼所在的登錄 Hive (位置)。我們希望監視位於 HKEY_LOCAL_MACHINE 的機碼,因此把 Hive 屬性的值設為 HKEY_LOCAL_MACHINE。如果我們希望監視位於 HKEY_CURRENT_USER 的登錄機碼,就設為 HKEY_CURRENT_USER。請注意,在設定 Hive 屬性時,不必定義和使用常數,只要輸入登錄 Hive 的實際名稱即可。
  • KeyPath。這是 Hive 裡面的路徑,通往我們的登錄機碼。由於 \ 是 WMI 的一個保留字元,必須在每一個 \ 另外加上第二個 \ 才行。因此,如果機碼路徑是 Software\Microsoft\Windows\CurrentVersion\Run,就必須改寫為 Software\\Microsoft\\Windows\\CurrentVersion\\Run。

發出查詢之後,我們再設定一個 Do 迴圈,讓它永遠執行,盡責的等候 RegistryKeyChangeEvent 類別的下一個執個體出現。我們可以利用下面這行程式碼,讓指令碼等候執行個體出現:

Set objLatestEvent = colEvents.NextEvent

這行程式碼會把指令碼「封鎖」起來,也就是說,指令碼只會在原地等候下一個事件發生 (如您所知,我們所監視的事件,就是 RegistryKeyChangeEvent 類別的執行個體)。當這類事件真的發生時,我們只要回應目前的日期和時間,以及登錄被修改的事實即可。接著就重演歷史,等候下一個事件發生。(如果要跳出迴圈,結束指令碼,請按 Ctrl+C)。

既然如此,為什麼我們不乾脆做得更徹底一點,而不只是注意登錄已被修改呢?那是因為我們不能這麼做:諸如變更什麼,以及由誰變更這種細節,並不是由登錄事件提供者擷取。我們可以擷取登錄機碼的初始狀態,等事件發生時,再比較新狀態和初始狀態,藉此判斷一部份的資訊。接著就必須設定程序,讓我們繼續比較登錄機碼的最新狀態與前一個狀態。但是這個就得交由您自己負責了。(當然嘍,如果有其他狀況發生,那就另當別論。畢竟我們還是得信守服務的承諾嘛!)


如需詳細資訊

請參閱嗨,Scripting Guy!- 過往文件

 

回到頁首 回到頁首