次の方法で共有


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 コードをパーティション分割、整理、抽象化できます。 モジュールには、コマンド (コマンドレットや関数など) と項目 (変数やエイリアスなど) である、1 つ以上の モジュール メンバーを含めることができます。 これらのメンバーの名前は、モジュールに対してプライベートに保持することも、"インポート" されるセッションに "エクスポート" することもできます。

には、マニフェスト、スクリプト、バイナリの 3 種類の モジュールがあります。 マニフェスト モジュール は、モジュールに関する情報を含み、そのモジュールの使用に関する特定の側面を制御するファイルです。 スクリプト モジュール は、.psm1の代わりに .ps1 のファイル拡張子を持つ PowerShell スクリプト ファイルです。 バイナリ モジュール には、コマンドレットとプロバイダーを定義するクラス型が含まれています。 スクリプト モジュールとは異なり、バイナリ モジュールはコンパイル済みの言語で記述されます。 バイナリ モジュールは、この仕様では扱われません。

バイナリ モジュールは、PowerShell ライブラリに対してコンパイルされた .NET アセンブリ (つまり DLL) です。

モジュールは "入れ子" にすることができます。つまり、あるモジュールにより別のモジュールをインポートできます。 関連する入れ子モジュールを持つモジュールは、ルート モジュールです。

PowerShell セッションが作成されると、既定ではモジュールはインポートされません。

モジュールをインポートする場合、モジュールの検索に使用される検索パスは、PSModulePath環境変数によって定義されます。

次のコマンドレットはモジュールを扱います。

  • Get-Module: インポート済みまたはインポート可能なモジュールを識別します
  • Import-Module: 現在のセッションに 1 つ以上のモジュールを追加します (§11.4を参照)
  • Export-ModuleMember: エクスポートするモジュール メンバーを識別します
  • Remove-Module: 現在のセッションから 1 つ以上のモジュールを削除します (§11.5を参照)
  • New-Module: 動的モジュールを作成します (§11.7を参照)

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

このモジュールには、それぞれエイリアスを持つ 2 つの関数が含まれています。 既定では、すべての関数名と関数名のみがエクスポートされます。 ただし、コマンドレット Export-ModuleMember を使用して何かをエクスポートすると、明示的にエクスポートされたもののみがエクスポートされます。 一連のコマンドと項目は、1 回の呼び出しまたはこのコマンドレットの複数の呼び出しでエクスポートできます。このような呼び出しは、現在のセッションに対して累積されます。

11.3 スクリプト モジュールのインストール

スクリプト モジュールはスクリプト ファイルで定義され、モジュールは任意のディレクトリに格納できます。 環境変数 PSModulePath は、モジュール関連のコマンドレットが完全修飾パスを含まない名前のモジュールを検索するときに検索される一連のディレクトリを指します。 追加の参照パスを指定できます。例えば

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

追加されたパスは、現在のセッションにのみ影響します。

または、モジュールのインポート時に完全修飾パスを指定することもできます。

11.4 スクリプト モジュールのインポート

モジュール内のリソースを使用する前に、コマンドレット Import-Moduleを使用して、そのモジュールを現在のセッションにインポートする必要があります。 Import-Module は、実際にインポートするリソースを制限できます。

モジュールがインポートされると、そのスクリプト ファイルが実行されます。 このプロセスは、スクリプト ファイルで 1 つ以上のパラメーターを定義し、Import-Moduleの ArgumentList パラメーターを使用して対応する引数を渡すことによって構成できます。

§11.2で定義されているこれらの関数とエイリアスを使用する次のスクリプトについて考えてみましょう。

Import-Module "E:\Scripts\Modules\PSTest_Temperature" - 詳細

"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 パラメーターを使用できます。 また、AliasコマンドレットFunction、および Variable パラメーターを使用すると、インポートするコマンドの選択を制限できるため、名前の競合が発生する可能性が低くなります。

コマンドが非表示の場合でも、コマンドの名前を元のモジュールの名前で修飾することで実行できます。 たとえば、 は、モジュール Mで F 関数を呼び出し、引数 100 を渡します。

同じ名前の同じ種類のコマンド (同じ名前の 2 つのコマンドレットなど) がセッションに含まれている場合、既定では、最後に追加されたコマンドが実行されます。

モジュールに関連するスコープの説明については、§3.5.6 を参照してください。

11.5 スクリプト モジュールの削除

コマンドレット Remove-Moduleを使用して、セッションから 1 つ以上のモジュールを削除できます。

モジュールを削除しても、モジュールはアンインストールされません。

スクリプト モジュールでは、次のように、そのモジュールが削除される前に実行されるコードを指定できます。

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

11.6 モジュール マニフェスト

§11.1で説明されているように、マニフェスト モジュールはモジュールに関する情報を含むファイルであり、そのモジュールの使用に関する特定の側面を制御します。

モジュールには対応するマニフェストは必要ありませんが、存在する場合、そのマニフェストは記述するモジュールと同じ名前を持ちますが、ファイル拡張子は .psd1

マニフェストには、一連のキーを含むハッシュテーブルを返す PowerShell スクリプトの限られたサブセットが含まれています。 これらのキーとその値は、そのモジュールに マニフェスト要素を指定します。 つまり、モジュールの内容と属性を記述し、前提条件を定義し、コンポーネントの処理方法を決定します。

基本的に、マニフェストはデータ ファイルです。ただし、データ型、if ステートメント、算術演算子と比較演算子への参照を含めることができます。 (割り当て、関数定義、およびループは許可されません)。マニフェストには環境変数への読み取りアクセス権もあり、コマンドレット Join-Pathの呼び出しを含めることができるため、パスを構築できます。

手記

エディターの注意: 元のドキュメントには、モジュール マニフェスト ファイルで許可されているキーの一覧が含まれています。 そのリストは古く、不完全です。 モジュール マニフェスト内のキーの完全な一覧については、「New-ModuleManifest参照してください。

必要な唯一のキーは、ModuleVersionです。

単純なマニフェストの例を次に示します。

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

GUID キーには 値があります。 これは、モジュールのグローバルに一意の IDentifier (GUID) を指定します。 GUID を使用して、同じ名前のモジュールを区別できます。 新しい GUID を作成するには、[guid]::NewGuid()メソッドを呼び出します。

11.7 動的モジュール

動的モジュール は、コマンドレット 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 では、モジュールの内容 (この場合は 2 つの関数と、それらの関数に対する 2 つのエイリアス) を定義します。 ディスク上のモジュールと同様に、関数のみが既定でエクスポートされるため、Export-ModuleMember コマンドレット呼び出しが存在し、関数とエイリアスの両方がエクスポートされます。

New-Module 実行すると、Convert-CentigradeToFahrenheit と c2f の呼び出しで示されているように、エクスポートされた 4 つの名前がセッションで使用できるようになります。

すべてのモジュールと同様に、動的モジュールのメンバーは、グローバル スコープの子であるプライベート モジュール スコープで実行されます。 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]::GetNewClosure (§4.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