如何从二进制(C#)模块调用PowerShell Cmdlet?

如何从二进制(C#)模块调用PowerShell Cmdlet?,c#,powershell,C#,Powershell,我正在编写一个自定义二进制(C#)Cmdlet,我想在此Cmdlet中调用另一个PowerShell二进制Cmdlet(例如Get ADUser),并将结果返回到我的Cmdlet中。实现这一目标的最佳方式是什么? 注意:在自定义Cmdlet中创建另一个PowerShell实例(如上所述)似乎不是实现这一点的最有效方法 我看了看问题。但是,它没有回答我的问题。如果可以引用实现cmdlet的类,则可以通过创建该类的实例来“调用”cmdlet,设置表示参数的所有属性,并调用cmdlet.Invoke(

我正在编写一个自定义二进制(C#)Cmdlet,我想在此Cmdlet中调用另一个PowerShell二进制Cmdlet(例如Get ADUser),并将结果返回到我的Cmdlet中。实现这一目标的最佳方式是什么? 注意:在自定义Cmdlet中创建另一个PowerShell实例(如上所述)似乎不是实现这一点的最有效方法


我看了看问题。但是,它没有回答我的问题。

如果可以引用实现cmdlet的类,则可以通过创建该类的实例来“调用”cmdlet,设置表示参数的所有属性,并调用
cmdlet.Invoke()
方法。下面是一个例子:

using System.Linq;
using System.Management.Automation;

namespace MyModule.Commands
{

    [Cmdlet(VerbsLifecycle.Invoke, "AnotherCmdlet")]
    public class InvokeAnotherCmdlet : Cmdlet
    {
        [Parameter(Mandatory = true)]
        public string Username { get; set; }

        protected override void ProcessRecord()
        {
            GetADUserCommand anotherCmdlet = new GetADUserCommand() {
                // Pass CommandRuntime of calling cmdlet to the called cmdlet (note 1)
                CommandRuntime = this.CommandRuntime, 

                // Set parameters
                Username = this.Username
            };

            // Cmdlet code isn't ran until the resulting IEnumerable is enumerated (note 2)
            anotherCmdlet.Invoke<object>().ToArray();
        }
    }

    [Cmdlet(VerbsCommon.Get, "ADUser")]
    public class GetADUserCommand : Cmdlet
    {
        [Parameter(Mandatory = true)]
        public string Username { get; set; }

        protected override void ProcessRecord()
        {
            WriteVerbose($"Getting AD User '{Username}'");
        }
    }
}
使用System.Linq;
使用系统、管理、自动化;
名称空间MyModule.Commands
{
[Cmdlet(VerbsLifecycle.Invoke,“另一个Cmdlet”)]
公共类InvokeAnotherCmdlet:Cmdlet
{
[参数(强制=真)]
公共字符串用户名{get;set;}
受保护的覆盖无效ProcessRecord()
{
GetADUserCommand anotherCmdlet=新的GetADUserCommand(){
//将调用cmdlet的CommandRuntime传递给被调用的cmdlet(注意1)
CommandRuntime=this.CommandRuntime,
//设置参数
Username=this.Username
};
//在枚举生成的IEnumerable之前,不会运行Cmdlet代码(注意2)
另一个cmdlet.Invoke().ToArray();
}
}
[Cmdlet(VerbsCommon.Get,“ADUser”)]
公共类GetADUserCommand:Cmdlet
{
[参数(强制=真)]
公共字符串用户名{get;set;}
受保护的覆盖无效ProcessRecord()
{
WriteVerbose($“获取广告用户{Username}'”);
}
}
}
有几件事需要注意:

  • 您可能希望将调用Cmdlet对象的
    Cmdlet.CommandRuntime
    属性的值传递给被调用的Cmdlet对象。这将确保,如果被调用的cmdlet写入对象流(例如,通过调用
    WriteObject
    ),这些对象将到达主机。另一种方法是调用cmdlet枚举调用cmdlet的
    Invoke()
    方法的结果
  • 在调用cmdlet上调用
    Invoke()
    方法不会像方法名称所示立即调用cmdlet。而是返回一个
    IEnumberable
    对象。枚举对象将调用该命令

  • 仅当要调用的Cmdlet从Cmdlet对象继承时,建议的方法才有效。换句话说,不能新建从PsCmdlet继承的Cmdlet。由于PsCmdlet公开了更多功能(例如访问Ps会话的能力),Windows附带的大多数Cmdlet都继承自PsCmdlet。因此,建议的方法具有有限的适用性。我对一个解决方案感兴趣,该解决方案将使用从PsCmdlet继承的Cmdlet。
    PsCmdlet
    继承
    Cmdlet
    ,因此它应该适用于所有Cmdlet类。