Slide 1

Slide 1 text

PowerShell モジュール開発入門 篠原敬志 (@karamem0)

Slide 2

Slide 2 text

自己紹介 Name 篠原敬志 (Takashi Shinohara) Company アバナード株式会社 シニアコンサルタント Award Microsoft MVP for Office Development (2018-) Twitter @karamem0 Facebook t.shinohara.56 Blog https://blog.karamem0.jp Bio 紅生姜ジャンキー 2

Slide 3

Slide 3 text

アジェンダ PowerShell モジュールの概要 PowerShell モジュールの開発 PowerShell モジュールのテスト PowerShell モジュールの CI/CD 3

Slide 4

Slide 4 text

PowerShell モジュールの概要

Slide 5

Slide 5 text

PowerShell とは .NET をベースとしたスクリプト言語 Window 7 以降の Windows に標準搭載 .NET のクロスプラットフォーム化に伴い PowerShell もバージョン 6 から .NET Core をターゲットにしたものに Windows PowerShell (~5.1) PowerShell Core (6.0~) バージョン 7 以降は名称が "PowerShell" に統合される 5

Slide 6

Slide 6 text

PowerShell の歴史 '06 '07 '08 '09 '10 '11 '12 '13 '14 '15 '16 '17 '18 '19 '20 XP Vista 7 8 8.1 10 2003 2008 2008 R2 2012 2012 R2 2016 2019 1.0 2.0 3.0 4.0 5.0 5.1 6.0 6.1 6.2 7.0 6

Slide 7

Slide 7 text

PowerShell モジュールとは PowerShell の再利用可能なライブラリ 一連のコマンドレット/関数/変数/エイリアス等をパッケージ化 モジュールごとに厳密に管理されたバージョン 作成したモジュールは NuGet リポジトリに公開可能 PowerShell Gallery MyGet Azure DevOps Artifacts 7

Slide 8

Slide 8 text

PowerShell Gallery 5,900 個 以上の 固有なパッケージ 12 億回 以上の ダウンロード 40,000 個 以上の 総パッケージ 8

Slide 9

Slide 9 text

公開されているモジュールの例 モジュール名 説明 SpeculationControl 脆弱性に対するパッチおよび軽減策の対応状況を確認する ためのモジュール Az Azure を操作するためのモジュール (旧名: AzureRM) AzureAD Azure Active Directory を操作するためのモジュール IISAdministration IIS を管理するためのモジュール AWSPowerShell AWS を操作するためのモジュール 9

Slide 10

Slide 10 text

PowerShell モジュールのインストール Install-Module コマンドレット (1 回のみ実行) Install-Module -Name -Scope CurrentUser Register-PSRepository コマンドレットでリポジトリを追加すること でプライベートなリポジトリからもインストール可能 10

Slide 11

Slide 11 text

PowerShell モジュールのインポート Import-Module コマンドレット (プロンプトの起動ごとに実行) Import-Module -Name 事前にモジュールをインポートしておきたい場合はプロファイルにイ ンポートを記述しておく PowerShell 3.0 からはモジュールの暗黙的なインポートがサポートさ れているためいきなりコマンドレットを記述してもOK 11

Slide 12

Slide 12 text

PowerShell モジュールの開発

Slide 13

Slide 13 text

PowerShell モジュールの要素 名前 説明 コマンドレット PowerShell で動作するコマンド (命令文)。標準で提供さ れるもののほかに C# で独自に作成することもできる。 関数 PowerShell スクリプトで記述される一連の操作を実行し 値を返すための機能。一般的なプログラミング言語の関数 とほとんど同じ。 変数 コマンドレットの結果などを格納するための領域。一般的 なプログラミング言語の変数とほとんど同じ。 エイリアス コマンドレットを短く記述するために付けられる別名。 13

Slide 14

Slide 14 text

PowerShell モジュールの種類 モジュールの種類 説明 スクリプト モジュール モジュール ファイル (.psm1) に PowerShell コード を記述する バイナリ モジュール .NET アセンブリ (.dll) に PowerShell コードを記述 する マニフェスト モジュール マニフェスト ファイル (.psd1) で単一または複数のモ ジュールを定義する ダイナミック モジュール ファイルとして保持せずインメモリ内で展開する この形式で作ることがほとんど 14

Slide 15

Slide 15 text

PowerShell モジュールの概念 マニフェスト モジュール (.psd1) スクリプト モジュール (.psm1) バイナリ モジュール (.dll) ダイナミック モジュール 15

Slide 16

Slide 16 text

マニフェスト ファイル (.psd1) モジュールに関するメタ データを記述するためのファイル マニフェストに関連付けられたモジュール モジュールのバージョン モジュールの作成者 サポートする PowerShell のバージョン 依存関係のあるモジュールやライブラリ エクスポートするコマンドレット/関数/変数/エイリアス コマンドレットで操作可能 New-ModuleManifest Update-ModuleMafinest 16

Slide 17

Slide 17 text

モジュールの形式の比較 項目 スクリプト モジュール バイナリ モジュール 言語 PowerShell C# または VB 規模 小~中規模 大規模 速度 低速 高速 コマンドレット 可能 難しい (不可能ではない) マネージ DLL 問題になることがある 可能 アンマネージ DLL (P/Invoke) 難しい (不可能ではない) 可能 17

Slide 18

Slide 18 text

スクリプト モジュールの開発 モジュール ファイル (.psm1) に関数/変数/エイリアスを記述する 関数/変数/エイリアスは Export-ModuleMember およびマニフェ スト ファイル (.psd1) で公開するかどうかを指定する モジュール ファイル (.psm1) にすべての関数/変数/エイリアスを 記述するとソースの可読性が下がるため、複数のスクリプト ファイル (.ps1) をドットソース読み込みする方法もある 18

Slide 19

Slide 19 text

スクリプト モジュール: Hello World モジュール ファイル (HelloWorld.psm1) function HelloWorld { [CmdletBinding()] param ( ) process { Write-Output 'Hello World!' } } 19

Slide 20

Slide 20 text

スクリプト モジュール: Hello World マニフェスト ファイル (Helloworld.psd1) @{ RootModule = 'HelloWorld.psm1' ModuleVersion = '1.0' } 20

Slide 21

Slide 21 text

スクリプト モジュール: Hello World モジュールのインポート PS C:¥HelloWorld> Import-Module '.¥HelloWorld.psd1' -PassThru ModuleType Version Name ExportedCommands ---------- ------- ---- ---------------- Script 1.0 HelloWorld HelloWorld 21

Slide 22

Slide 22 text

バイナリ モジュールの開発 以下のターゲットでプロジェクトを作成する Windows PowerShell の場合: .NET Framework 4.7.2 PowerShell Core の場合: .NET Core 2.1 PowerShellStandard.Library を NuGet から参照する コマンドレットは PSCmdlet クラスを継承し CmdletAttribute 属性 を付ける 22

Slide 23

Slide 23 text

バイナリ モジュール: Hello World ソース コード (HelloWorld.cs) [Cmdlet("Write", "HelloWorld")] [Alias("helloworld")] public class HelloWorld : PSCmdlet { protected override void ProcessRecord() { this.WriteObject("Hello World!"); } } 23

Slide 24

Slide 24 text

バイナリ モジュール: Hello World マニフェスト ファイル (HelloWorld.psd1) @{ RootModule = 'HelloWorld.dll' ModuleVersion = '1.0' } 24

Slide 25

Slide 25 text

バイナリ モジュール: Hello World モジュールのインポート PS C:¥HelloWorld> Import-Module '.¥bin¥Debug¥net472¥HelloWorld.psd1' -PassThru ModuleType Version Name ExportedCommands ---------- ------- ---- ---------------- Binary 1.0 HelloWorld {Write-HelloWorld, helloworld} 25

Slide 26

Slide 26 text

PowerShell モジュールのテスト

Slide 27

Slide 27 text

Pester とは PowerShell 標準でインストールされている PowerShell スクリプト の単体テストのためのモジュール https://github.com/pester/Pester 27

Slide 28

Slide 28 text

Pester の構文 名前 説明 Describe 複数の Context または It をグループ化する Context Context の中で複数の It をグループ化する It 実行されるテスト スクリプトを定義する BeforeEach 各 It の実行前に実行されるスクリプトを定義する AfterEach 各 It の実行後に実行されるスクリプトを定義する Should テストの実行結果を比較し失敗をスローする Mock 既存のコマンドレットをモックする Invoke-Pester テストを実行する 28

Slide 29

Slide 29 text

Pester のアサーションの例 名前 説明 Be 指定した値と等しいことを検証する BeGreaterThan 指定した値より大きいことを検証する BeGreaterOrEqual 指定した値より等しいか大きいことを検証する BeLessThan 指定した値より小さいことを検証する BeLessOrEqual 指定した値より等しいか小さいことを検証する BeOfType 指定した型であることを検証する Match 正規表現に一致することを検証する Throw 例外を発生させることを検証する Not 他のアサーションの意味を反転させる 29

Slide 30

Slide 30 text

Pester によるテスト: Hello World テスト スクリプト (HelloWorld.Tests.ps1) Import-Module './HelloWorld.psd1' -Force Describe 'Tests HelloWorld' { Context 'Positive Test' { It 'Returns HelloWorld' { HelloWorld | Should -Be 'Hello World!' } } } 30

Slide 31

Slide 31 text

Pester によるテスト: Hello World テストの実行 PS C:¥HelloWorld> Import-Module Pester PS C:¥HelloWorld> Invoke-Pester Executing script C:¥HelloWorld¥HelloWorld.Tests.ps1 Describing Tests HelloWorld Context Positive Test [+] Returns HelloWorld 90ms Tests completed in 505ms Tests Passed: 1, Failed: 0, Skipped: 0, Pending: 0, Inconclusive: 0 31

Slide 32

Slide 32 text

MSTest によるテスト 単体テスト プロジェクトで NuGet からパッケージを参照する Windows PowerShell の場合: PowerShellStandard.Library PowerShell Core の場合: Microsoft.PowerShell.SDK Microsoft.PowerShell.Commands.Diagnostics Microsoft.PowerShell.Commands.Management Microsoft.PowerShell.Commands.Utility Microsoft.PowerShell.ConsoleHost Microsoft.WSMan.Management Microsoft.WSMan.Runtime 32

Slide 33

Slide 33 text

C# からの PowerShell の実行 Windows PowerShell と PowerShell Core で書き方が異なる Windows PowerShell の場合: PowerShell オブジェクトにコマン ド名やパラメーターの情報を設定して実行する PowerShell Core の場合: Runspace と Pipeline を作成し、 Pipeline オブジェクトにコマンド名やパラメーターの情報を設定し て実行する 実行結果は PSObject (PowerShell の汎用オブジェクト) として取得 できる 33

Slide 34

Slide 34 text

Windows PowerShell からの実行 ソース コード var powershell = PowerShell.Create(); powershell.Commands.Clear(); powershell.AddCommand("Import-Module"); powershell.AddParameter("Name", "./HelloWorld.psd1"); powershell.Invoke(); powershell.Commands.Clear(); powershell.AddCommand("helloworld"); var outputs = powershell.Invoke(); var result = outputs[0].BaseObject; Assert.AreEqual("Hello World!", result); 34

Slide 35

Slide 35 text

PowerShell Core からの実行 ソース コード var runspace = RunspaceFactory.CreateRunspace(); runspace.Open(); var pipeline1 = runspace.CreatePipeline(); var command1 = new Command("Import-Module"); command1.Parameters.Add("Name", "./HelloWorld.psd1"); pipeline1.Commands.Add(command1); pipeline1.Invoke(); var pipeline2 = runspace.CreatePipeline(); var command2 = new Command("helloworld"); pipeline2.Commands.Add(command2); var outputs = pipeline2.Invoke(); var result = outputs[0].BaseObject; Assert.AreEqual("Hello World!", result); 35

Slide 36

Slide 36 text

PowerShell モジュールの CI/CD

Slide 37

Slide 37 text

Azure DevOps を使った CI/CD Azure Repos GitHub Git Server Azure Pipelines Azure Artifacts PowerShell Gallery 37

Slide 38

Slide 38 text

Azure Pipelines ビルドとデプロイのプロセスを自動化するため の機能 Build Pipeline: ビルドと自動テストを実行 し Artifacts を作成する Release Pipeline: 作成された Artifacts を 環境にデプロイする Multi-stage Pipeline: Build Pipeline と Release Pipeline に代わって新しく提供され るパイプラインの形式 38

Slide 39

Slide 39 text

Azure Artifacts 作成した NuGet や npm などのパッケージを 管理するためのリポジトリとパッケージを公開 するためのフィードを提供 作成したパッケージを Azure Pipelines に組み 込むことが可能 39

Slide 40

Slide 40 text

PowerShell Gallery への発行 PowerShell Gallery へのログ イン https://www.powershellgall ery.com 40

Slide 41

Slide 41 text

PowerShell Gallery への発行 API キーの発行 41

Slide 42

Slide 42 text

PowerShell Gallery への発行 コマンドレットの実行 Publish-Module -Name -NuGetApiKey Marketplace から Azure DevOps 向けの拡張機能を入手可能 PowerShell Gallery Publisher https://marketplace.visualstudio.com/items?itemName=k enakamu.PSGalleryPublisher 42

Slide 43

Slide 43 text

Azure Artifacts への発行 NuGet パッケージの作成 43

Slide 44

Slide 44 text

Azure Artifacts への発行 NuGet パッケージの発行 44

Slide 45

Slide 45 text

Azure Artifacts への発行 Azure Artifacts のフィードに 発行されたパッケージ 45

Slide 46

Slide 46 text

Azure Artifacts への発行 Azure Artifacts のリポジトリを PowerShell に追加 Register-PSRepository -Name 'PowershellAzureDevopsS ervices' -SourceLocation 'https://.pkgs.vi sualstudio.com/_packaging//nuget/v2' -Pub lishLocation 'https://.pkgs.visualstudio.c om/_packaging//nuget/v2' -InstallationPol icy Trusted 発行されたパッケージのインストール Install-Module -Name 'HelloWorld' -Repository 'Powe rshellAzureDevopsServices' -Scope CurrentUser 46

Slide 47

Slide 47 text

まとめ

Slide 48

Slide 48 text

サンプル コード スクリプト モジュール https://dev.azure.com/karamem0jp/PowerShell-ScriptModul e-HelloWorld バイナリ モジュール https://dev.azure.com/karamem0jp/PowerShell-BinaryModu le-HelloWorld 48

Slide 49

Slide 49 text

参考リンク The Next Release of PowerShell – PowerShell 7 https://devblogs.microsoft.com/powershell/the-next-release -of-powershell-powershell-7/ PowerShell モジュールをインポートする https://docs.microsoft.com/ja-jp/powershell/scripting/devel oper/module/importing-a-powershell-module Use Azure Artifacts as a private PowerShell repository https://docs.microsoft.com/en-us/azure/devops/artifacts/tu torials/private-powershell-library 49