Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to share properties and comments between Powershell cmdlets in c#?

When exposing a set of related functions in Powershell cmdlets, is it possible to share the property names and summary help to normalize these across cmdlets in an assembly?

I know that this can be done with derived classes, but this solution is awkward at best when there are multiple cmdlets with different properties to be shared.

Here is an extremely simple example. I would like to share the property 'Name' and all related comments so that they are the same across the N cmdlets we are producing, but I cannot think of a good way to do this in c#. Ideally any sharing would allow specification of Parameter attributes such as Mandatory or Position.

namespace FrozCmdlets
{
using System.Management.Automation;

/// <summary>
/// Adds a new froz to the system.
/// </summary>
[Cmdlet( VerbsCommon.Add, "Froz" )]
public class AddFroz : Cmdlet
{
    /// <summary>
    /// The name of the froz.
    /// For more information on the froz, see froz help manual.
    /// </summary>
    [Parameter]
    public string Name { get; set; }

    protected override void ProcessRecord()
    {
        base.ProcessRecord();
        // Add the froz here
    }
}

/// <summary>
/// Removes a froz from the system.
/// </summary>
[Cmdlet( VerbsCommon.Remove, "Froz" )]
public class RemoveFroz : Cmdlet
{
    /// <summary>
    /// The name of the froz.
    /// For more information on the froz, see froz help manual.
    /// </summary>
    [Parameter]
    public string Name { get; set; }

    protected override void ProcessRecord()
    {
        base.ProcessRecord();
        // Remove the froz here
    }
}
}
like image 380
pennyowe Avatar asked Jun 28 '12 22:06

pennyowe


1 Answers

Yes, there is a way to do this without inheriting from a common base class for the parameters. Its not not well documented, only hinted at in the IDynamicParameters.GetDynamicParameters method's remarks. Here's a more detailed treatment of the topic.

First, create a class with your common parameters declared as properties with the [Parameter] attributes:

internal class MyCommonParmeters
{
    [Parameter] 
    public string Foo { get; set; }
    [Parameter]
    public int Bar { get; set; }
    ...
}

Then each Cmdlet that wants to use these common parameters should implement the IDynamicParameters interface to return a member instance of the MyCommonParameters class:

[Cmdlet(VerbsCommon.Add, "Froz")]
public class AddFroz : PSCmdlet, IDynamicParameters
{
    private MyCommonParmeters MyCommonParameters 
        = new MyCommonParmeters();

    object IDynamicParameters.GetDynamicParameters()
    {
        return this.MyCommonParameters;
    }
    ...

With this approach, the PowerShell command parameter binder will find and populate the parameters on the MyCommonParameters instance just as if they were members of the Cmdlet classes.

like image 182
Burt_Harris Avatar answered Oct 23 '22 14:10

Burt_Harris