共用方式為


11. 模組

編輯附註

重要

Windows PowerShell 語言規格 3.0 於 2012 年 12 月發行,並以 Windows PowerShell 3.0 為基礎。 此規格不會反映 PowerShell 的目前狀態。 沒有計劃更新此檔以反映目前的狀態。 此文件在此提供以供歷史參考。

規格文件可從 Microsoft 下載中心取得,作為 Microsoft Word 文件:https://www.microsoft.com/download/details.aspx?id=36389 該 Word 文件已轉換以在 Microsoft Learn 上呈現。 在轉換期間,已進行一些編輯變更,以配合 Docs 平臺的格式設定。 已修正某些錯字和次要錯誤。

11.1 簡介

•3.14中所述,模組是一個獨立可重複使用的單元,可讓 PowerShell 程式代碼進行分割、組織及抽象化。 模組可以包含一或多個 模組成員,也就是命令(例如 Cmdlet 和函式)和專案(例如變數和別名)。 這些成員的名稱可以保留在模組的私用狀態,或是 匯出至模組 匯入的會話。

模組有三種類型:manifest、腳本和二進位檔 指令清單模組 是包含模組相關信息的檔案,並控制該模組使用的某些層面。 指令碼模組 是副檔名為 .psm1 的 PowerShell 指令碼檔案,而不是 .ps1二進位模組 包含定義 Cmdlet 和提供者的類別類型。 不同於腳本模組,二進位模組是以編譯的語言撰寫。 此規格未涵蓋二進位模組。

二進位模組是針對PowerShell連結庫編譯的 .NET 元件(亦即 DLL)。

模組可能會 嵌套;也就是說,一個模組可能會匯入另一個模組。 具有相關聯巢狀模組的模組是 根模組

建立 PowerShell 工作階段時,預設不會匯入任何模組。

匯入模組時,用來尋找它們的搜尋路徑是由環境變數定義,PSModulePath

下列 Cmdlet 會處理模組:

11.2 撰寫腳本模組

腳本模組是腳本檔案。 請考慮下列文稿模組:

function Convert-CentigradeToFahrenheit ([double]$tempC) {
    return ($tempC * (9.0 / 5.0)) + 32.0
}
New-Alias c2f Convert-CentigradeToFahrenheit

function Convert-FahrenheitToCentigrade ([double]$tempF) {
    return ($tempF - 32.0) * (5.0 / 9.0)
}
New-Alias f2c Convert-FahrenheitToCentigrade

Export-ModuleMember -Function Convert-CentigradeToFahrenheit
Export-ModuleMember -Function Convert-FahrenheitToCentigrade
Export-ModuleMember -Alias c2f, f2c

此模組包含兩個函式,每個函式都有別名。 根據預設,會匯出所有函式名稱,而且只會匯出函式名稱。 不過,一旦 cmdlet Export-ModuleMember 用來匯出任何項目,只有那些被明確指定匯出的項目才會被匯出。 一系列的命令和項目可以在一次或多次呼叫這個 Cmdlet 時進行匯出;這些呼叫會在當前會話中累積。

11.3 安裝腳本模組

腳本模組定義於腳本檔案中,而且模組可以儲存在任何目錄中。 當模組相關 Cmdlet 尋找名稱不包含完整路徑的模組時,PSModulePath 環境變數會指向一組要搜尋的目錄。 您可以提供其他查閱路徑;例如

$Env:PSModulePath = $Env:PSModulePath + ";<additional-path>"

新增的任何其他路徑只會影響目前的會話。

或者,匯入模組時可以指定完整路徑。

11.4 匯入腳本模組

使用模組中的資源之前,必須使用 Cmdlet Import-Module,將該模組匯入目前的會話。 Import-Module 可以限制實際匯入的資源。

匯入模組時,會執行其腳本檔案。 您可以在腳本檔案中定義一或多個參數,並透過 Import-Module的 ArgumentList 參數傳入對應的自變數,以設定該程式。

請考慮下列腳本,使用了在 §11.2中定義的這些函式和別名:

Import-Module “E:\Scripts\Modules\PSTest_Temperature” -Verbose

"0 degrees C is " + (Convert-CentigradeToFahrenheit 0) + " degrees F"
"100 degrees C is " + (c2f 100) + " degrees F"
"32 degrees F is " + (Convert-FahrenheitToCentigrade 32) + " degrees C"
"212 degrees F is " + (f2c 212) + " degrees C"

當模組中的命令或專案與會話中的命令或專案名稱相同時,匯入模組會導致名稱衝突。 名稱衝突會導致隱藏或取代名稱。 Import-Module 的 Prefix 參數可用來避免命名衝突。 此外,別名Cmdlet函式,以及 Variable 參數可以限制要匯入的命令選取範圍,進而減少名稱衝突的機會。

即使是被隱藏的命令,也可以透過使用其來源模組的名稱來限定命令名稱以執行它。 例如,& M\F 100 在模組 M中叫用 F 函式,並傳遞自變數 100。

當會話包含具有相同名稱之相同類型的命令時,例如具有相同名稱的兩個 Cmdlet,預設會執行最近新增的命令。

如需瞭解與模組相關的範圍,請參閱 §3.5.6

11.5 移除腳本模組

您可以透過 Cmdlet Remove-Module,從會話中移除一或多個模組。

拿掉模組並不會卸載模組。

在文稿模組中,您可以指定在移除該模組之前執行的程式代碼,如下所示:

$MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = { *on-removal-code* }

11.6 模組指令清單

第11.1條所述,清單模組是包含有關模組資訊的檔案,並控制該模組使用的某些方面。

模組不需要有對應的指令清單,但如果有,該指令清單的名稱與所描述的模組相同,但擴展名為 .psd1

指令清單包含有限的 PowerShell 腳本子集,它會傳回包含一組索引鍵的哈希表。 這些索引鍵及其值會指定該模組的 清單元素。 也就是說,他們會描述模組的內容和屬性、定義任何必要條件,以及判斷元件的處理方式。

基本上,清單是一個數據檔;不過,它可以包含對數據類型的引用、if 語句,以及算術運算符和比較運算符。 (不允許指派、函式定義和迴圈。指令清單也具有環境變數的讀取許可權,而且它可以包含對 Cmdlet Join-Path的呼叫,因此可以建構路徑。

注意

編輯器的附註:源檔包含模組指令清單檔中允許的索引鍵清單。 該清單已過期且不完整。 如需模組指令清單中索引鍵的完整清單,請參閱 New-ModuleManifest

唯一需要的鍵是 ModuleVersion

以下是一個簡單的清單範例:

@{
ModuleVersion = '1.0'
Author = 'John Doe'
RequiredModules = @()
FunctionsToExport = 'Set*','Get*','Process*'
}

金鑰 GUID 具有 string 值。 這會指定模組的全域唯一識別碼 GUID。 GUID 可用來區分具有相同名稱的模組。 若要建立新的 GUID,請呼叫 方法 [guid]::NewGuid()

11.7 動態模組

動態模組 是在執行時由 Cmdlet New-Module於記憶體中建立的模組;它不會從磁碟載入。 請考慮下列範例:

$sb = {
    function Convert-CentigradeToFahrenheit ([double]$tempC) {
        return ($tempC * (9.0 / 5.0)) + 32.0
    }

    New-Alias c2f Convert-CentigradeToFahrenheit

    function Convert-FahrenheitToCentigrade ([double]$tempF) {
        return ($tempF - 32.0) * (5.0 / 9.0)
    }

    New-Alias f2c Convert-FahrenheitToCentigrade

    Export-ModuleMember -Function Convert-CentigradeToFahrenheit
    Export-ModuleMember -Function Convert-FahrenheitToCentigrade
    Export-ModuleMember -Alias c2f, f2c
}

New-Module -Name MyDynMod -ScriptBlock $sb
Convert-CentigradeToFahrenheit 100
c2f 100

腳本區塊 $sb 定義模組的內容,在此案例中,這些函式有兩個函式和兩個別名。 如同磁碟上的模組,預設只會匯出函式,因此 Export-ModuleMember Cmdlet 呼叫存在以匯出函式和別名。

執行 New-Module 之後,導出的四個名稱就可用於會話,如呼叫 Convert-CentigradeToFahrenheit 和 c2f 所示。

如同所有模組,動態模組的成員會在全域範圍的子系私人模組範圍中執行。 Get-Module 無法取得動態模組,但 Get-Command 可以取得導出的成員。

若要讓動態模組可供 Get-Module使用,請使用管線將 New-Module 命令傳送至 Import-Module,或使用管線將 New-Module 傳回的模組物件傳送至 Import-Module。 此動作會將動態模組新增至 Get-Module 清單,但不會將模組儲存至磁碟或讓它持續運作。

11.8 關閉

動態模組可用來建立 閉包,即附加有數據的函式。 請考慮下列範例:

function Get-NextID ([int]$StartValue = 1) {
    $nextID = $StartValue
    {
        ($Script:nextID++)
    }.GetNewClosure()
}

$v1 = Get-NextID      # get a scriptblock with $StartValue of 0
& $v1                 # invoke Get-NextID getting back 1
& $v1                 # invoke Get-NextID getting back 2

$v2 = Get-NextID 100  # get a scriptblock with $StartValue of 100
& $v2                 # invoke Get-NextID getting back 100
& $v2                 # invoke Get-NextID getting back 101

此處的意圖是,Get-NextID 傳回可以指定起始值之序列中的下一个ID。 不過,必須支援多個序列,每個序列都有自己的 $StartValue$nextID 內容。 這是透過呼叫 方法 [scriptblock]::GetNewClosure4.3.7來達成此目的。

每次 GetNewClosure建立新的閉包時,都會建立新的動態模組,並將呼叫端範圍中的變數(本案例中為包含增量的腳本區塊)複製到這個新的模組中。 為了確保父函式內定義的 nextId(但腳本區塊外部)會遞增,需要明確的 Script:範圍前置詞。

當然,腳本區塊不需要是具名函式;例如:

$v3 = & {      # get a scriptblock with $StartValue of 200
    param ([int]$StartValue = 1)
    $nextID = $StartValue
    {
        ($Script:nextID++)
    }.GetNewClosure()
} 200

& $v3          # invoke script getting back 200
& $v3          # invoke script getting back 201