🔍

PowerShell モジュールで変数をエクスポートするときの挙動について

に公開

はじめに

PowerShell モジュールで変数をエクスポートするときの挙動について、うまくいかない点があったため整理します。

スクリプトで Export-ModuleMember を呼び出さない場合

まずは Export-ModuleMember を呼び出さない場合を確認します。HelloWorld.psm1 という名前でファイルを作成し、各スコープごとに変数を宣言します。

$private:HelloWorldPrivate = 'HelloWorld'
$local:HelloWorldLocal = 'HelloWorld'
$script:HelloWorldScript = 'HelloWorld'
$global:HelloWorldGlobal = 'HelloWorld'

このモジュールを読み込んだときに使用できる変数は以下のようになります。

PS C:\> Import-Module .\HelloWorld.psm1
PS C:\> Get-ChildItem variable: | where Name -like 'HelloWorld*'

Name                           Value
----                           -----
HelloWorldGlobal               HelloWorld

global スコープで宣言した変数以外は使用できないことがわかります。

スクリプトで Export-ModuleMember を呼び出す場合

先ほどの HelloWorld.psm1 に Export-ModuleMember を追加します。

$private:HelloWorldPrivate = 'HelloWorld'
$local:HelloWorldLocal = 'HelloWorld'
$script:HelloWorldScript = 'HelloWorld'
$global:HelloWorldGlobal = 'HelloWorld'

Export-ModuleMember -Variable '*'

同じようにモジュールを読み込みます。

PS C:\> Import-Module .\HelloWorld.psm1
PS C:\> Get-ChildItem variable: | where Name -like 'HelloWorld*'

Name                           Value
----                           -----
HelloWorldGlobal               HelloWorld
HelloWorldLocal                HelloWorld
HelloWorldPrivate              HelloWorld
HelloWorldScript               HelloWorld

すべてのスコープについて変数がエクスポートされていることがわかります。

マニフェストで VariablesToExport を指定しない場合

スクリプト ファイル (psm1 ファイル) を直接モジュールとして読み込むのではなく、マニフェスト ファイル (psd1 ファイル) を使うことが多いため、こちらの動作も確認します。まずは VariablesToExport を指定しない、つまり空の配列を指定した状態で試します。

@{
RootModule = 'HelloWorld.psm1'
ModuleVersion = '1.0'
VariablesToExport = @()
}

この状態でモジュールを読み込みます。

PS C:\> Import-Module .\HelloWorld.psd1
PS C:\> Get-ChildItem variable: | where Name -like 'HelloWorld*'

Name                           Value
----                           -----
HelloWorldGlobal               HelloWorld

Export-ModuleMember と同様に global スコープで宣言した変数のみが使用できます。

マニフェストで VariablesToExport を指定した場合

次に VariablesToExport を指定します。

@{
RootModule = 'HelloWorld.psm1'
ModuleVersion = '1.0'
VariablesToExport = '*'
}

同様にモジュールを読み込みます。

PS C:\> Import-Module .\HelloWorld.psd1
PS C:\> Get-ChildItem variable: | where Name -like 'HelloWorld*'

Name                           Value
----                           -----
HelloWorldGlobal               HelloWorld

Export-ModuleMember のときとは異なり、global 以外の変数がエクスポートされていません。

おわりに

一通り試してみて、以下のことがわかりました。

  • Export-ModuleMember を呼び出さなくても global スコープの変数は使用できる
  • Export-ModuleMember を呼び出すとどのスコープでも変数はエクスポートされる
  • マニフェストの VariablesToExport は無視される

では VariablesToExport は何をするのかという疑問が残ります。バイナリ モジュールでも変数のエクスポートはできません。いずれにしても変数をエクスポートする場合は明示的に Export-ModuleMember を呼び出すことをおすすめします。

Discussion