iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
💻

Implementing Write-Verbose effectively in C# Binary Modules

に公開

Introduction

By the way, this post is not late; I am just filling in the gap for the 16th, which was empty.

About Write-Verbose

In PowerShell, you can output trace information by using the Verbose parameter. Within a module, you control the output by calling Write-Verbose. For Script Modules, you just call the cmdlet from a PowerShell script, so no special consideration is needed, but the situation is different for Binary Modules. The Cmdlet.WriteVerbose method is not static. If it is a simple cmdlet, writing it inside the ProcessRecord method is sufficient, but this is not the case once it reaches a certain scale. Also, passing around a Cmdlet instance is not recommended.

Utilizing Trace.WriteLine

C# has the Trace.WriteLine method. I wondered if I could use this method, but by default, there is no mechanism to pipe Trace.WriteLine output to the PowerShell host. Therefore, you need to implement a custom TraceListener.

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);
    }
}

By implementing it this way, you can output messages to the host simply by calling Trace.WriteLine from anywhere, provided the Verbose parameter is specified. Since this results in a loosely coupled design, testing also becomes easier.

Discussion