托管的PowerShell无法在同一个程序集中看到Cmdlet

我正在尝试从我的C#代码运行PowerShell脚本,它将使用运行它们的程序集中的自定义Cmdlet。 这是代码:

using System; using System.Management.Automation; [Cmdlet(VerbsCommon.Get,"Hello")] public class GetHelloCommand:Cmdlet { protected override void EndProcessing() { WriteObject("Hello",true); } } class MainClass { public static void Main(string[] args) { PowerShell powerShell=PowerShell.Create(); powerShell.AddCommand("Get-Hello"); foreach(string str in powerShell.AddCommand("Out-String").Invoke()) Console.WriteLine(str); } } 

当我尝试运行它时,我得到一个CommandNotFoundException。 我写错了Cmdlet吗? 有什么我需要做的事情来在PowerShell或Runspace中注册我的Cmdlet吗?

使用当前代码段执行此操作的最简单方法如下:

 using System; using System.Management.Automation; [Cmdlet(VerbsCommon.Get,"Hello")] public class GetHelloCommand:Cmdlet { protected override void EndProcessing() { WriteObject("Hello",true); } } class MainClass { public static void Main(string[] args) { PowerShell powerShell=PowerShell.Create(); // import commands from the current executing assembly powershell.AddCommand("Import-Module") .AddParameter("Assembly", System.Reflection.Assembly.GetExecutingAssembly()) powershell.Invoke() powershell.Commands.Clear() powershell.AddCommand("Get-Hello"); foreach(string str in powerShell.AddCommand("Out-String").Invoke()) Console.WriteLine(str); } } 

这假设是PowerShell v2.0(您可以使用$ psversiontable或版权日期检查您的控制台,应该是2009年。)如果您使用的是win7,那么您将使用v2。

另一种简单的方法是在运行空间配置中注册cmdlet,使用此配置创建运行空间,并使用该运行空间。

 using System; using System.Management.Automation; using System.Management.Automation.Runspaces; [Cmdlet(VerbsCommon.Get, "Hello")] public class GetHelloCommand : Cmdlet { protected override void EndProcessing() { WriteObject("Hello", true); } } class MainClass { public static void Main(string[] args) { PowerShell powerShell = PowerShell.Create(); var configuration = RunspaceConfiguration.Create(); configuration.Cmdlets.Append(new CmdletConfigurationEntry[] { new CmdletConfigurationEntry("Get-Hello", typeof(GetHelloCommand), "") }); powerShell.Runspace = RunspaceFactory.CreateRunspace(configuration); powerShell.Runspace.Open(); powerShell.AddCommand("Get-Hello"); foreach (string str in powerShell.AddCommand("Out-String").Invoke()) Console.WriteLine(str); } } 

以防万一,使用此方法cmdlet类不必公开。

您需要先注册cmdlet,然后才能在Powershell会话中使用它。 你通常会通过Powershell Snap-In来做到这一点。 以下是该过程的高级概述:

  • 创建自定义cmdlet(您已经完成了此部分)
  • 创建一个Powershell管理单元,其中包含并描述了您的cmdlet
  • 使用Installutil在系统上安装新的管理单元
  • 使用Add-PSSnapin将Snap-in添加到特定的Powershell会话中

MSDN上有一些有用的文章可以非常彻底地解释这个过程:

  • 使用Windows PowerShell进行开发
  • 如何创建Windows PowerShell管理单元

还有一个由两部分组成的关于ByteBlocks的系列文章,讨论编写自定义cmdlet。 这个系列可能是你最好的选择,因为你似乎已经完成了相同的第1部分。 您可以使用第2部分作为快速参考,并且可以继续使用。

  • 如何编写自定义Cmdlet – 第1部分
  • 如何编写自定义Cmdlet – 第2部分