🛠️

Windows PowerShell と PowerShell Core に対応した PowerShell モジュールを作成する

2022/01/01に公開

この記事は PowerShell Advent Calendar 2019 に参加しています。

https://qiita.com/advent-calendar/2019/powershell

はじめに

PowerShell の新しいバージョンである PowerShell Core が提供されて久しいですが、PowerShell モジュールを開発して一般に提供するような場合、互換性を考えて、旧来の Windows PowerShell をサポートしなければならないことがあります。Windows PowerShell は .NET Framework で動作し、PowerShell Core は .NET Core で動作するので、両方に対応したモジュールを作成するにはちょっとした工夫が必要です。

モジュールを PowerShell スクリプトで記述する

PowerShell スクリプト (この場合は .psm1) は実行される PowerShell のバージョンの影響を受けないため、Windows PowerShell と PowerShell Core のどちらでも動作します。ただし PowerShell Core での破壊的変更には注意する必要があります。

https://docs.microsoft.com/ja-jp/powershell/scripting/whats-new/breaking-changes-ps6?WT.mc_id=PS-MVP-5002941

また、PowerShell スクリプトが外部のライブラリ (.dll ファイル) に依存する場合、そのライブラリが .NET Standard で作られている必要があります。

マニフェスト ファイルで動的にモジュールを読み込む

モジュールをバイナリ (.dll ファイル) で開発する場合、マニフェスト ファイル (.psd1 ファイル) では RootModule の宣言に対して関数を受けられるようになっており、その中で $PSEdition を判断して読み込むモジュールを変更することができます。.NET Framework と .NET Core の両方でビルドする必要はありますが、安全にモジュールを読み込むことができます。詳細については以下に記載されています。

https://docs.microsoft.com/ja-jp/powershell/scripting/gallery/concepts/module-psedition-support?WT.mc_id=PS-MVP-5002941

モジュールを .NET Standard で作成する

モジュールを .NET Standard (netstandard2.0) でビルドすることで Windows PowerShell と PowerShell Core の両方で動作させることができます。これは Az モジュールが使っている方法になります。この方法の一番の問題は PowerShell のコア ライブラリである System.Management.Automation.dll の参照になるのですが、以下のように GAC をパス指定で強引に読み込むことで解決します。実行時には必ず System.Management.Automation.dll は読み込まれているので、問題になることはありません。

<ItemGroup>
  <Reference Include="System.Management.Automation">
    <HintPath>C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf3856ad364e35\System.Management.Automation.dll</HintPath>
    <Private>false</Private>
  </Reference>
</ItemGroup>

この場合も、依存関係のある外部のライブラリについても .NET Standard 化されていないと厳しいと思います。

おわりに

依存関係もまとめて解決できるので、マニフェスト ファイルで制御するのが最も確実な方法になります。とはいえ、他の方法も悪いというわけではないので、状況に応じて使っていただければよいかと思います。

Discussion