Start-Service alerter -computer atl-fs-01
但不是現在。
儘管如此,我們還是可以在遠端電腦上取得警訊器服務的資訊。這又是怎麼一回事呢?原來 Get-WMIObject (英文) cmdlet 並不在限制之內,Get-WMIObject 可以用 piggybacks 進入 WMI,借用 WMI 的能力操作遠端電腦:無須依賴 Windows PowerShell cmdlets 連線,Get-WMIObject 自己就可以用 WMI 完成一樣的工作。
這裡有一個原則:只要您用的是 WMI 屬性和方法,就可以靠 Get-WMIObject 操作遠端電腦。否則 Windows PowerShell 只能用來操作本機電腦。(雖然我們不清楚 Windows PowerShell 何時能夠操作遠端電腦,但是這一點有朝一日會改進。)
使用 Get-WMIObject 搭配標準的 WMI 方法 (例如 StartService) 在遠端電腦上啟動服務,背後有什麼意義嗎?當然有意義,而且其中還有玄機,咱們先來瞧瞧在遠端電腦啟動服務的 Windows PowerShell 指令碼/命令,再給讀者說明:
(Get-WmiObject -computer atl-fs-01 Win32_Service -Filter "Name='Alerter'").InvokeMethod("StartService",$null)
這個命令是由兩個部分組成,一個連接至警訊服務,另一個啟動服務。先介紹第一部份,連接至 WMI 服務:
(Get-WmiObject -computer atl-fs-01 Win32_Service -Filter "Name='Alerter'")
連線至 atl-fs-01 電腦上的 WMI 服務,然後把 Name 屬性等於 Alerter 的 Win32_Service 類別通通擷取下來。這裡的動作用 VBScript 程式碼表達就相當於:
Set objWMIService = GetObject("winmgmts:\\atl-fs-01")
Set colServiceList = objWMIService.ExecQuery _
("Select * From Win32_Service Where Name='Alerter'")
看清楚囉,我們並不呼叫 Windows PowerShell 方法裡的 ExecQuery 方法,而是使用 –Filter 參數,指定只需要傳回 Name 等於 Alerter 的服務。
問得好:Get-WMIObject 陳述式為何要用括弧括住呢?這是為了確保 Windows PowerShell 把傳回的物件「當作物件看待」,以便用來呼叫方法。取得物件之後,在右括弧後加上一個點 (.),一如 VBScript 中的作法。在 Windows PowerShell 命令中輸入:
(Get-WmiObject -computer atl-fs-01 Win32_Service -Filter "Name='Alerter'").InvokeMethod("StartService",$null)
如果是 VBScript 則輸入 (大多數在 For Each 迴圈內):
objItem.StartService
懂了嗎?好,更麻煩的還在後頭。命令的第二個部分中,並不直接呼叫 StartService 方法,而是:
InvokeMethod("StartService",$null)
這行的目的何在?這麼說好了,呼叫 Get-WMIObject 後的確傳回了物件,但這是 .NET Framework 物件 (明確的說,是 System.Management.ManagementObject#root\cimv2\Win32_Service object)。沒辦法呼叫 StartService 方法,原因很簡單:這類物件沒有 StartService 方法。所以我們改呼叫 InvokeMethod 方法,傳出兩個參數:
- "StartService",想叫用的 WMI 方法名稱。
- $Null,也就是 Null 值。
InvokeMethod 接受兩個參數:被呼叫的參數,後接方法所需的額外引數。本例中並沒有方法引數。但是不管參數存不存在,nvokeMethod 一定要兩個參數。為了滿足 InvokeMethod 的要求,我們傳一個 NULL 值給第二個參數。
又一個好問題:我們是怎麼知道傳回的物件是 System.Management.ManagementObject#root\cimv2\Win32_Service 物件,而且它不支援 StartService 方法呢?我是很想回答,「因為我們很聰明,無所不知」,不過應該沒人會信吧。那我們就老實回答好了,方法是取得指定物件,用 Get-Member (英文) cmdlet 跑過,取得屬性和方法清單。也就是:
Get-WmiObject Win32_Service -Filter "Name='Alerter'" | Get-Member
這裡用了一套老招數,從錯誤中不斷嘗試,直到找出啟動服務的方法。
在此有幾點要聲明,我們提出的方法的確可行,但並不表示這就是最佳或唯一可行的途徑。如果您有更棒的方法可以用 Windows PowerShell 達到相同的目的,請與我們分享,因為我們自己也正在摸索這項新技術。(福山博士,我們非常想聽一聽您的意見!)
為了使本文討論不要太過深入,我們跳過了 Windows PowerShell 的功能和原理這類的技術細節。這些資訊現在還不重要,因為我們的目的是讓讀者對 Windows PowerShell 的運作方式,以及在某些情況下仍無法運作 (至少是現在) 的原因有粗淺的認識。對了,我們還介紹了如何使用 Windows PowerShell 在遠端電腦上啟動服務。這就是今天的重點,
順便向世人證明太陽底下依然有新鮮事,這點我覺得表現得相當不錯。 |