简体   繁体   中英

Executing Powershell Cmdlets Code in C#

How would I use the code used to create powershell cmdlets in another c# method instead of a powershell script.

I have the following code:

public class Program
{
    static void Main(string[] args)
    {
        var getCommand = new GetCommand { Text = "Hello World"};

        //help needed here
    }
}

[Cmdlet("Test", "Get")]
public class GetCommand : Cmdlet
{
    [Parameter(Mandatory = true)]
    public string Text { get; set; }

    protected override void ProcessRecord()
    {
        WriteObject(Text);
    }
}

Don't instantiate the GetCommand class - PowerShell will do that for you!

First, you'll need to spin up an instance of the PowerShell class to execute your command:

PowerShell ps = PowerShell.Create();

Then add a CommandInfo reference with the AddCommand method:

ps.AddCommand(new CmdletInfo("Test-Get", typeof(GetCommand)));

And then add your parameter argument:

ps.AddParameter("Text", "Hello World");

Now you can execute it (and collect the output) with the Invoke() method:

var output = ps.Invoke();
foreach(var obj in ouput)
{
    Console.WriteLine("Output was: {0}", obj);
}

Extract the logic in a seperate class and call it directly. Use the cmdlet to be, well, just a shell around this new class. This Seperation of Concerns (SoC) also enables easier unit tests and leads to an overall cleaner architecture.

Extracted Class Greeter.cs

public class Greeter {
    public Greeter(string name) {
        _Name = name;
    }
    private string _Name;
    public string SayHello() {
        return $"Hello {_Name}";
    }
    public string SayGoodBye() {
        return $"So long {_Name}, and thanks for all the fish!";
    }
}

CommandLet GetGreetingCommand.cs

[Cmdlet("Greeting", "Get")]
public class GetGreetingCommand : Cmdlet {
    [Parameter(Mandatory = true)]
    public string Name { get; set; }

    protected override void ProcessRecord() {
        var greeter = new Greeter(Name);
        var greeting = greeter.SayHello();
        WriteObject(greeting);
    }
}

CommandLet GetGoodByeCommand .cs

[Cmdlet("GoodBye", "Get")]
public class GetGoodByeCommand : Cmdlet {
    [Parameter(Mandatory = true)]
    public string Name { get; set; }

    protected override void ProcessRecord() {
        var greeter = new Greeter(Name);
        var goodBye = greeter.SayGoodBye();
        WriteObject(goodBye);
    }
}

Console Main.cs (or any other client-code of Greeter-class)

public static void main(string[] args) {
    var greeter = new Greeter(args.FirstOrDefault());
    Console.WriteLine(greeter.SayHello());
    Console.WriteLine(greeter.SayGoodBye());
}

TestCase

public static void SayingHelloUsesName() {
    var sut = new Greeter("Arthur");

    var expected = "Hello Arthur";
    var actual = sut.SayHello();

    Assert.AreEqual(expected, actual);
}

The two concerns here are - the actual BusinessLogic (Greeter.cs) - interoperability with PowerShell, providing mechanisms to parameterize the cmdlet, etc. (Get*Command.cs). As you see, the cmdlets really only pass through the calls, while enabling use via PowerShell.

@Mathias R. Jessen ´ answer could be usefull, if you need to call third party cmdlets, but in most cases, there should be an appropriate (non-powershell) API for what you are trying to do.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM