💻
Binary Module (C#) でいい感じに Write-Verbose したい
はじめに
この記事は PowerShell Advent Calendar 2018 の参加記事です。
ちなみに投稿が遅れたのではなく 16 日が埋まっていなかったので穴埋めしています。ここ重要!
Write-Verbose について
PowerShell では Verbose
パラメーターを付けることでトレース情報を出力させることができます。モジュールの内部では Write-Verbose
を呼び出すことで出力内容を制御します。Script Module の場合、PowerShell のスクリプトからコマンドレットを呼び出すだけなので、特に何も考える必要はないのですが、Binary Module の場合は勝手が違います。なぜなら、Cmdlet.WriteVerbose
メソッドは static
ではないからです。単純なコマンドレットであれば、ProcessRecord
メソッドで全部書けば済むかもしれません。ある程度の規模になってくるとそうもいきません。かといって Cmdlet
のインスタンスを持ち回すのも美しいとは思えません。
Trace.WriteLine があるじゃないか
C# には Trace.WriteLine
メソッドがあります。こいつを使えばいけるのではと思いましたが、標準では Trace.WriteLine
をホストに流し込んでくれるような仕組みにはなっていないようです。[1] 仕方がないので TraceLister
を自作します。
CmdletTraceListener.cs
public class CmdletTraceListener : TraceListener
{
private readonly Cmdlet cmdlet;
public CmdletTraceListener(Cmdlet cmdlet)
{
if (cmdlet == null)
{
throw new ArgumentNullException(nameof(cmdlet));
}
this.cmdlet = cmdlet;
}
public override void Write(string message)
{
this.cmdlet.WriteVerbose(message);
}
public override void WriteLine(string message)
{
this.cmdlet.WriteVerbose(message);
}
}
TraceableCmdlet.cs
public abstract class TraceableCmdlet : PSCmdlet
{
private readonly TraceListener traceListener;
protected TraceableCmdlet()
{
this.traceListener = new CmdletTraceListener(this);
}
protected override void BeginProcessing()
{
Trace.Listeners.Add(this.traceListener);
base.BeginProcessing();
}
protected override void EndProcessing()
{
base.EndProcessing();
Trace.Listeners.Remove(this.traceListener);
}
}
こうしてあげることで、どこからでも Trace.WriteLine
を呼び出すだけで (Verbose
パラメーターを指定していれば) ホストにメッセージが出力されますし、疎結合になるのでテストも容易になるのではないかと思います。
-
Console.WriteLine
はWrite-Host
と同様に動作します。 ↩︎
Discussion