【问题标题】:Hosted PowerShell cannot see Cmdlets in the same Assembly托管的 PowerShell 看不到同一程序集中的 Cmdlet
【发布时间】:2011-09-27 06:43:06
【问题描述】:

我正在尝试从我的 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<string>())
            Console.WriteLine(str);
    }
}

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

【问题讨论】:

    标签: c# powershell powershell-cmdlet


    【解决方案1】:

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

    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<string>()) 
                Console.WriteLine(str); 
        } 
    } 
    

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

    【讨论】:

      【解决方案2】:

      另一种简单的方法是在运行空间配置中注册 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<string>())
                  Console.WriteLine(str);
          }
      }
      

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

      【讨论】:

      • 谢谢。有没有办法从 PowerShell 内部做到这一点?即使用 [Reflection.Assembly]::LoadFrom 加载 DLL,然后调用将 Cmdlet 加载到当前 PowerShell 会话的函数?
      • 我没有尝试过(只是因为没有必要)。在 PowerShell 中,您可以访问默认(或多或少 current 但这取决于)运行空间的配置:[System.Management.Automation.Runspaces.Runspace]::DefaultRunspace.RunspaceConfiguration。然后尝试拨打.Cmdlets.Append(...)就可以了。如果你试试这个并告诉我们结果会很好。
      • 我无法让它工作。似乎运行空间不会以这种方式加载 Cmdlet,除非它处于 BeforeOpen 状态。有什么方法可以将 Cmdlet 加载到已经打开的运行空间?
      【解决方案3】:

      您确实需要先注册您的 cmdlet,然后才能在 Powershell 会话中使用它。您通常会通过 Powershell 管理单元来执行此操作。以下是该过程的高级概述:

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

      在 MSDN 上有几篇有用的文章非常彻底地解释了该过程:

      还有一个关于 ByteBlocks 的 2 部分系列讨论编写自定义 cmdlet。该系列可能是您最好的选择,因为您似乎已经完成了与第 1 部分相当的工作。您也许可以将第 2 部分用作快速参考,然后就可以开始了。

      【讨论】:

      • SnapIn 是 powershell v1 的做事方式,现在不鼓励使用,因为它需要管理权限才能注册它们。他应该使用 powershell v2 模块。
      • 并没有真正回答他想要做什么的问题。
      • @manojlds 它确实回答了这个问题,但绝对不像 x0n 的回答那样最新或优雅。
      • @x0n 我赞成您的回答,因为它更加优雅,并且具有独立性的额外好处。
      猜你喜欢
      • 2019-07-09
      • 1970-01-01
      • 1970-01-01
      • 2011-07-11
      • 2012-02-29
      • 1970-01-01
      • 2013-12-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多