Windows PowerShell:封裝與散發自訂 Windows PowerShell 工具

您可以利用 Dot-source 功能實現一些有趣的功能,但如果您不夠謹慎,它也可能會帶來一些問題。

Don Jones

Dot-source 是一種巧妙的技巧,但如果您不再需要某些命令,或者如果您後來發現某些命令與其他內容衝突,卻很難刪除這些命令。 當我們在上個月將一個命令變為獨立的、參數化的可重用工具之後,我發現我們需要解決兩個問題。

我們將該工具構建為 Windows PowerShell 高級函數,有時也稱為“腳本 Cmdlet”。第一個問題是,腳本本身難以使用。 該腳本包含一個函數,因此如果只運行該腳本,不會發生任何事。 您要麼修改該腳本並添加用來運行該函數的命令,要麼通過 Dot-source 將該腳本轉移到 Shell 中,才能使該函數成為一個全域命令。

另一問題是,該腳本包含兩個函數。 第一個函數是 Get-OSInfo,是我希望使用者使用的函數。 第二個函數是 OSInfoWorker,它完成了所有實際的工作。 但是,我不希望使用者直接執行這個函數。 如果使用 Dot-source 方式,則沒有辦法隱藏 OSInfoWorker(或者按照程式師的說法,將它變為私有)。 將腳本轉變成腳本模組可解決這兩個問題。

瞭解模組

Windows PowerShell 支援三種基本的模組類型:二進位、腳本和清單模組。 二進位模組包含一個在 Visual Studio 中生成的 DLL,用於向 Shell 添加 Cmdlet、提供程式或其他元素。 腳本模組僅僅是指:單一的腳本,可向 Shell 添加一個或多個函數。 清單模組可真正包含多個元件,例如二進位擴展程式、腳本等等。 腳本模組最容易創建,因此我們選擇使用腳本模組。

腳本模組有三項要求:

  1. 它必須是有效的 Windows PowerShell 腳本,主要由要添加到 Shell 中的函陣列成。
  2. 它必須具有 .psm1 檔副檔名,而不是 .ps1 檔副檔名。
  3. 它必須位於電腦上的特定資料夾中

最後一條要求實際上不過是為方便起見而提供的一項建議。 在安裝時,Windows PowerShell 會定義一個新的系統級環境變數,名為 PSModulePath。 此環境變數的工作方式與系統的 Path 環境變數非常相似。 它包含 Shell 在按名稱查找模組時自動搜索的資料夾。

預設情況下,會定義兩個模組路徑。 其中一個位於 System32 資料夾層次結構下。 此路徑供 Microsoft 提供的模組使用。 另一個位於您的 Documents 資料夾中,供您自己的模組使用。 我們將使用這一個路徑。 當然,您可以在 PSModulePath 中修改或添加路徑,例如,定義您的團隊用來集中存儲共用模組的路徑。

我們使用的路徑是 \[My ]Documents\WindowsPowerShell\Modules。 在 Windows XP,此路徑為“My Documents”。 而在 Windows Vista 及更高版本中,此路徑僅為“Documents”。 預設情況下,WindowsPowerShell 資料夾不存在。 您必須自行創建。 預設情況下,Modules 子資料夾也不存在,因此您也需要自行創建。

如果不將您的模組放到某個 PSModulePath 位置中,則只需在載入模組時,指定完整的路徑和檔案名。 這種方式對於常用模組不是很方便,因此我傾向于將其放到 PSModulePath 中定義的路徑下。

構建模組

我將在上個月的腳本末尾加上三個命令(您可以在此下載修訂後的腳本):

New-Alias goi Get-OSInfo
Export-ModuleMember -function Get-OSInfo
Export-ModuleMember -alias goi

第一個命令定義一個別名“goi”。它用於我的 Get-OSInfo 函數。 其他兩個命令僅當您在腳本模組中使用它們時才會生效。

預設情況下,當您將一個模組導入 Shell 中時,將公開提供該模組中的每個函數。 但是當您使用 Export-ModuleMember 時,則只會公開提供那些明確命名的函數和別名。

我的“goi”別名以及 Get-OSInfo 函數就能由任何使用此模組的使用者使用。 而我未指定的函數 OSInfoWorker 將被隱藏。 您仍然可以在模組本身內部使用任何函數來調用 OSInfoWorker,但它不能直接在模組外使用,因為它是私有函數。

添加了這些命令後,我需要為該腳本指定適當的名稱並將其放到適當的位置。 我選擇將此模組命名為“MyModule”。因此,該指令檔的路徑應當為 \[My ]Documents\WindowsPowerShell\Modules\MyModule\MyModule.psm1。

該腳本必須放到 Modules 的子資料夾中。 子資料夾和指令檔本身的名稱都必須與模組名相同。 做完此操作後,我就可以運行 Import-Module MyModule 來載入我的模組。

這是向其他使用者分發腳本的一種簡單而又有效的方法。 我可以根據需要,在這一個檔中包含任意數量的函數和別名。 只要將其放到正確的位置(或者有人願意指定完整路徑),其他使用者就能輕鬆載入該模組,並使用這些函數。

Don Jones

Don Jones 是 Concentrated Technology 的創始人,他會在 ConcentratedTech.com 上解答有關 Windows PowerShell 和其他技術的問題。 他也是 Nexus.Realtimepublishers.com 的撰稿人,他的許多著作還在他的網站上以電子版的形式提供。

獲取更多內容

下載本月文章隨附的示例代碼

註冊即將截止,請趕快註冊參加 Jones 親自主持的獨家動手體驗工作室,該工作室為期三天,與 TechMentor Spring 2011 在同一地點舉行。 有關詳情,請訪問 TechMentorEvents.com

相關內容