首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Windows 自動化腳本實戰:用 WMI 啟動程式並監控退出後關閉另一程式

     編輯:Java 相關知識

雖然標題提到 Java,但原文實際展示的是一段 **VBScript / WMI 腳本**,用於在 Windows 環境下啟動兩個程式(計算機與記事本),監聽第一個程式退出事件,隨即終止第二個程式。這類腳本常用於系統管理、測試環境編排或 CI/CD 前置腳本。本文將原始碼重構為可讀性更強的版本,並詳細解析核心 WMI 查詢與事件監聽機制。

需求場景

  • 啟動程式 A(如 calc.exe)與程式 B(如 notepad.exe)。
  • 程式 A 為「觸發程式」,程式 B 為「被監控程式」。
  • 當使用者關閉程式 A 時,腳本自動強制關閉程式 B 並結束自身。

完整腳本代碼 (VBScript)

' ===== 啟動兩個程式並取得 Process ID =====
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2:Win32_Process")

' 啟動計算機
errResult = objWMIService.Create("calc.exe", Null, Null, intCalcID)
If errResult <> 0 Then WScript.Echo "啟動 calc.exe 失敗, 錯誤碼: " & errResult : WScript.Quit

' 啟動記事本
errResult = objWMIService.Create("notepad.exe", Null, Null, intNotepadID)
If errResult <> 0 Then WScript.Echo "啟動 notepad.exe 失敗, 錯誤碼: " & errResult : WScript.Quit

WScript.Echo "✅ 兩程式已啟動 | Calc PID: " & intCalcID & " | Notepad PID: " & intNotepadID

' ===== 重新連線至通用 WMI 命名空間以訂閱事件 =====
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

' 訂閱「進程刪除事件」:每 1 秒輪詢一次 __InstanceDeletionEvent
Set colProcesses = objWMIService.ExecNotificationQuery _
    ("Select * From __InstanceDeletionEvent Within 1 Where TargetInstance ISA 'Win32_Process'")

WScript.Echo "👀 開始監聽進程退出事件... (關閉計算機將觸發關閉記事本)"

' ===== 事件迴圈:等待計算機退出 =====
Do Until i = 999 ' 永真迴圈,靠 Exit Do 跳出
    Set objProcess = colProcesses.NextEvent ' 阻塞直到下一個刪除事件
    If objProcess.TargetInstance.ProcessID = intCalcID Then
        WScript.Echo "🎯 偵測到計算機 (PID " & intCalcID & ") 已退出"
        Exit Do
    End If
Loop

' ===== 終止記事本 =====
Set colProcesses = objWMIService.ExecQuery _
    ("Select * From Win32_Process Where ProcessID = " & intNotepadID)

For Each objProcess In colProcesses
    objProcess.Terminate()
    WScript.Echo "🛑 已終止記事本 (PID " & intNotepadID & ")"
Next

WScript.Echo "✅ 腳本任務完成,正常結束。"

核心技術點解析

1. Win32_Process.Create 啟動程式並獲取 PID

  • 回傳值 0 表示成功,非零請查 MSDN 錯誤碼。
  • 第四參數 intCalcID 為 **輸出參數**,接收新建進程的 ProcessID。
  • 若需指定工作目錄或啟動參數,可填入第 2、3 參數(此處用 Null)。

2. __InstanceDeletionEvent 事件監聽

  • WMI 事件模型:每當實例被刪除,系統產生 __InstanceDeletionEvent,其 TargetInstance 屬性指向被刪除的實例(此處為 Win32_Process)。
  • Within 1 表示輪詢間隔 1 秒(WMI 事件非即時推送,而是輪詢模擬)。
  • ISA 'Win32_Process' 過濾只關心進程刪除事件。

3. ExecNotificationQuery vs ExecQuery

方法用途行為
ExecNotificationQuery事件訂閱回傳事件集合,NextEvent 會**阻塞**直到下一個事件到達
ExecQuery靜態查詢立即回傳符合條件的實例集合,可用 For Each 遍歷

4. 遠端電腦支援

將 strComputer = "." 改為目標電腦名稱或 IP(需管理員權限、RPC/WMI 通訊埠開放、防火牆允許)。注意:遠端啟動的 GUI 程式在 **Session 0 隔離** 下不可見,僅適合無互動的後台程式。

Java 整合建議

若需在 Java 中調用,可透過 Runtime.getRuntime().exec("wscript.exe /path/to/script.vbs") 或 ProcessBuilder 執行;更優雅的方式是使用 JNA 或 J-Interop 直接呼叫 WMI COM 介面,避免外部腳本依賴。

常見問題排查

  • 腳本無反應/報「存取被拒」:以系統管理員身分執行 cmd.exe 再跑腳本,或檢查 WMI 安全性設定 (wmimgmt.msc)。
  • 事件遲遲不觸發:Within 間隔過大,或 WMI 服務 (Winmgmt) 異常,重啟服務嘗試。
  • PID 重用導致誤殺:極罕見,但長時間運行腳本時 PID 可能被系統回收重用。生產環境建議額外校驗 Name 或 CommandLine 屬性。

結語

WMI 是 Windows 系統管理的瑞士刀。掌握 Win32_Process 生命週期操作(建立、查詢、終止)與 __InstanceDeletionEvent 事件訂閱模式,即可構建強大的自動化編排腳本。雖然 PowerShell 如今更主流,但 VBScript/WMI 組合在舊版 Windows (XP/Server 2003) 仍具相容性優勢,理解其原理有助於跨技術棧的問題排查。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved