Hosted PowerShell cannot see Cmdlets in the same Assembly

前端 未结 3 1200
暖寄归人
暖寄归人 2020-12-17 22:21

I\'m trying to run PowerShell scripts from my C# code, that will use custom Cmdlets from the assembly that runs them. Here is the code:



        
相关标签:
3条回答
  • 2020-12-17 23:02

    You do need to register your cmdlet before you can use it in a Powershell session. You'll generally do that by way of a Powershell Snap-In. Here's a high-level overview of the process:

    • Create custom cmdlets (you've already done this part)
    • Create a Powershell Snap-in which contains and describes your cmdlets
    • Install the new Snap-in on your system using Installutil
    • Add the Snap-in to a specific Powershell session using Add-PSSnapin

    There are a couple useful articles on MSDN that explain the process pretty thoroughly:

    • Developing with Windows PowerShell
    • How to Create a Windows PowerShell Snap-in

    There's also a 2-part series on ByteBlocks that discusses writing custom cmdlets. That series may be your best bet, since you seem to have done the equivalent of part 1 already. You may be able to just use part 2 as a quick reference and be good to go.

    • How to Write a Custom Cmdlet - Part 1
    • How to Write a Custom Cmdlet - Part 2
    0 讨论(0)
  • 2020-12-17 23:08

    The easiest way to do this with your current code snippet is like this:

    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); 
        } 
    } 
    

    This assumes PowerShell v2.0 (you can check in your console with $psversiontable or by the copyright date which should be 2009.) If you're on win7, you are on v2.

    0 讨论(0)
  • 2020-12-17 23:12

    Yet another simple way is to register cmdlets in a runspace configuration, create a runspace with this configuration, and use that runspace.

    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);
        }
    }
    

    Just in case, with this approach cmdlet classes do not have to be public.

    0 讨论(0)
提交回复
热议问题