Scripting Guy 為您解答問題

Hey, Scripting Guy!

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

資源

如何使用 Windows PowerShell 來取得電腦上所有已開啟視窗的清單?

Hey, Scripting Guy! Question

嗨,Scripting Guy!有人告訴我可以使用 Windows PowerShell 來取得電腦上所有已開啟視窗的清單。您是否可以告訴我怎麼做?

        -- JD

Hey, Scripting Guy! Answer

JD,您好。沒錯,我們可以告訴您。但是,在告訴您怎麼做之前,我們想要花點時間向 Peter Costantini (最年長的 Scripting Guy) 致意。因為 Peter 身為 Dr. Scripto 指令碼工廠 (英文) 的作者、加上他在網路廣播上唱歌的瘋狂行徑而聲名大噪,他最近接受了 Microsoft 管理實務群組的程式經理職位。Peter 將仍然是 Scripting Guy,他只是無法花更多時間撰寫指令碼或 Script Center 的文章而已。

總而言之,這會讓他與其他 Scripting Guy 具備相同的立場。但是,至少他有不做事的藉口。

就其他 Scripting Guy 而言,我們祝福 Peter 好運,而且為了讚揚他,我們想要概述他身為 Scripting Guy 的一些最偉大時刻:

  • 舉例來說,他在幾週之前...呃,實際上是 Dean 做的。

  • 而 Peter 在一年前...算我沒說;好像是 Jean 寫的。

  • 還有就是...喔,算了。但是,如果房子沒有失火的話,這會是相當好的一小段指令碼。

當然,還有許多其他偉大的時刻,呃,族繁不及備載。

附註:如您所知,Peter 對於指令碼和 Script Center 真正的貢獻無法用他的工作量來衡量。至少,他一直告訴我們大家這點。 不過,往好的方面想,Peter 這幾年來花不少時間做一些無用或不重要的事,確實讓他成為 Microsoft 公司管理職位的理所當然的選擇。

老實說,當 Peter 宣佈他要離開時,我們的第一個反應就是悶悶不樂地呆坐著(當然,這通常是我們對任何事的第一個反應)。但是,Peter 不希望我們有這種表現,他希望我們能繼續努力工作。好吧,Peter,下面的工作都是為你做的:

Script Center
Get-Process | Where-Object {$_.MainWindowTitle -ne ""} | Select-Object MainWindowTitle

如您所見,這是一個蠻簡單的小命令。我們一開始先呼叫 Get-Process Cmdlet (如名稱所示,它會擷取電腦上執行之所有處理序的集合)。當然,我們並不是真的需要電腦上執行之所有處理序的集合。畢竟,這種集合包含了不在可見視窗內執行的服務和其他處理序。因此,我們將該集合「傳送」至 Where-Object Cmdlet,並要求 Where-Object 篩選掉 MainWindowTitle 屬性不等於空字串以外的所有處理序。

附註:是!我們知道:在 Windows PowerShell 中,您可以使用 -ne 運算子來取代 <>。而這點完全與我們喜歡 使用 -ne 與否無關,只是必須使用 -ne 而已。

然後,這樣會產生什麼結果呢?這樣做將會濾除不在可見視窗內執行的服務和其他處理序 (如果沒有任何視窗,則 MainWindowTitle 等於空字串)。然後,我們要將這個經過篩選的集合傳遞給 Select-Object Cmdlet 並要求 Select-Object 僅顯示 MainWindowTitle 屬性:

MainWindowTitle
---------------
open_windows.ps1 - Notepad
Inbox - Microsoft Outlook
Windows PowerShell
more_hey_scripting_guy.doc - Microsoft Word

重要觀察:在 WMI 的 Win32_Process 類別中,您完全找不到 MainWindowTitle 屬性。這是因為 Get-Process Cmdlet 並非使用 WMI 來擷取處理序資訊,而是使用 .NET Frameowork 類別 System.Diagnostics.Process

不幸的是,這個命令有一個小缺點:它不會傳回任何 Windows 檔案總管的視窗 (例如,開啟 C:\Scripts 的視窗)。但是,沒關係,還有另一行程式碼傳回 Windows 檔案總管的視窗:

$a = New-Object -com "Shell.Application"; $b = $a.windows() | select-object LocationName; $b

我們在此使用 New-Object Cmdlet 來建立 Shell.Application 物件的執行個體。接著,我們會呼叫 Windows() 方法來擷取 Shell 視窗的集合,然後使用 Select-Object Cmdlet 來回應 LocationName 屬性的值。接著就產生類似下面所示的報告:

LocationName
------------
Stuff
Hey Scripting Guy
Scripts

或者,您也可以回應 LocationURL 屬性來取得完整路徑。當然,在這種情況下,您可能也想要進行某些清除工作,因為 LocationURL 傳回路徑的方式就像下面這樣:

file:///C:/Documents%20and%20Settings/kenmyer/Desktop/Stuff/Hey%20Scripting%20Guy

但是,這裡有一則命令 (英文) 可能會對於清除該字串有所幫助。

希望上述說明能回答您的問題,JD。偷偷告訴您,在 Peter 接受新職位之後,我們絕對不會奪走他的 Scripting Guy 身分。這是不是因為他對於指令碼界具有卓越貢獻,所以我們期待他能在未來幾年持續作出貢獻呢?這是當然的囉。

嗯,除了以上的原因外,另一個理由是,如果我們擺脫了 Peter,那麼 Greg 就會成為最年長的 Scripting Guy,而且 Greg 絕對不會接受這個事實。看到了嗎,Peter?雖然我們喜歡捉弄你,讓你的日子不好過,但是你一直在這個小組裡扮演非常重要的角色。永遠都是。