PowerShell では、 .NET の資産を簡単に呼び出すことができます。
つまり、 Base64 エンコードのような煩雑な処理も、 base64.exe
のような外部依存なしに行えるということです。
しかし、 .NET を呼び出す記述は冗長になりがちで、対話シェルで使うにはあまりに面倒です。
そこで、 PowerShell のメンバを動的に追加する機能を使うことで、 "STR".ToBase64
のように短い記述で処理を呼び出せるようにします。
TL;DR
- 拡張型データを使い、型にメソッドを追加する
- Types.ps1xml を
Update-TypeData
で読み込むことでメソッドを追加できる
どうやって追加するか
PowerShell の機能の一つに Extended Type System (ETS) というものがあります。
これは、型に対してメンバーを動的に追加したりするための仕組みで、「タイプドリブン」な PowerShell で型名を気にせずスクリプトを書けるのはこの仕組みのおかげです。
今回は、 ETS の「拡張型データ」に ToBase64
プロパティを追加することで、 "STR".ToBase64
のような記述を実現します。
「分かった」気になれる言い方をするなら、 PowerShell の豊富な機能の一つを使って String
に ToBase64
プロパティを追加するという言い方になるのでしょう。
ちなみに、 ETS では PSObject
という神クラスが重要な役割を果たしているらしいです。詳しい説明は マイクロソフトの Extended Type System に関するドキュメント にあるので興味がある方は読んでみてください。
実際にメソッドを追加する
では、 String
型に対して ToBase64
プロパティを追加してみましょう。
まずは、追加する ToBase64
の実装を考えます。とりあえず、以下のような単純な実装にしてみました。
function ToBase64([String] $str)
{
// [System.Text.Encoding]::Unicode を使っているため、 UTF-16 の文字列としてエンコードされるので注意
[System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($str))
}
次に、 Types.ps1xml
を書きます。ファイル名は何でも構いませんが、拡張子は ps1xml
でなくてはなりません。
Types.ps1xml
のリファレンスは Types.ps1xml にありますので、必要に応じて読んでください。
<?xml version="1.0" encoding="utf-8" ?>
<Types>
<Type>
<!-- System.String 型に対してデータを追加する -->
<Name>System.String</Name>
<Members>
<!-- `"foo".ToBase64` のように呼び出したいので、「 Script の返り値が値となるようなプロパティ」を定義する -->
<ScriptProperty>
<!-- プロパティ名は `ToBase64` にする -->
<Name>ToBase64</Name>
<!-- 実行するスクリプトを定義する。引数としてインスタンス自身、つまり $this を渡す -->
<GetScriptBlock>
[System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($this))
</GetScriptBlock>
</ScriptProperty>
</Members>
</Type>
</Types>
最後に、 PowerShell で Types.ps1xml
を読み込みます。
PS C:\> Update-Typedata -PrependPath .\Types.ps1xml
PS C:\> "example".ToBase64
ZQB4AGEAbQBwAGwAZQA=
PS C:\> # ToBase64 が呼び出せた!
Update-TypeData
で読み込んだデータは、シェルが終了すると消えてしまいます。シェル起動時に自動的に読み込まれるようにするには、 Profiles で Update-TypeData
を呼び出すとよいでしょう。
なお、この節で説明した内容は about_Types.ps1xml - PowerShell | Microsoft Docs の Example: Adding an Age member to FileInfo objects の節 とほぼ同じですので、分からないところなどあればそちらを読んでください。