Erfassen der ausführlichen Ausgabe eines Powershell-CmdLet, wenn das CmdLet über C # programmgesteuert aufgerufen wird

HINTERGRUNDIch verwende Powershell 2.0 unter Windows 7.Ich schreibe ein Cmdlet in ein Powershell-Modul ("Modul" ist neu in Powershell 2.0).Zum Testen des Cmdlets schreibe ich Unit-Tests in Visual Studio 2008, mit denen das Cmdlet programmgesteuert aufgerufen wird.REFERENZDieser Artikel über MSDN In "Aufrufen eines Cmdlets aus einem Cmdlet heraus" wird gezeigt, wie ein Cmdlet aus C # aufgerufen wird.DER QUELLENCODE

Dies ist eine destillierte Version meines aktuellen Codes. Ich habe sie so klein wie möglich gemacht, damit Sie das Problem, das ich habe, klar erkennen können:

using System;
using System.Management.Automation;   

namespace DemoCmdLet1
{
    class Program
    {
        static void Main(string[] args)
        {
            var cmd = new GetColorsCommand();

                foreach ( var i in cmd.Invoke<string>())
                {
                   Console.WriteLine("- " + i );   
                } 
           } 
       } 

    [Cmdlet("Get", "Colors")]
    public class GetColorsCommand : Cmdlet
    {
        protected override void ProcessRecord()
        {
            this.WriteObject("Hello");
            this.WriteVerbose("World");
        }

    }
}
BEMERKUNGENIch verstehe, wie man ausführliche Ausgaben über die Powershell-Befehlszeile aktiviert und aufzeichnet. Das ist nicht das Problem.In diesem Fall rufe ich das Cmdlet programmgesteuert in C # auf.Nichts, was ich gefunden habe, spricht mein spezifisches Szenario an. Einige Artikel schlagen vor, dass ich meinen eigenen PSHost implementieren sollte, aber es scheint teuer zu sein und es scheint, als müsste das Cmdlet als Text aufgerufen werden, was ich vermeiden möchte, da dieser nicht so stark typisiert ist.UPDATE AM 20.07.2009

Hier ist der Quellcode basierend auf der Antwort unten.

Einige Dinge sind mir immer noch nicht klar: * Wie man das Cmdlet "Get-Colors" aufruft (idealerweise ohne es als String an das ps-Objekt übergeben zu müssen) * Wie man die ausführliche Ausgabe erhältwie es erzeugt wird anstatt am Ende eine Sammlung von ihnen zu bekommen.

    using System;
    using System.Management.Automation;   

    namespace DemoCmdLet1
    {
        class Program
        {
            static void Main(string[] args)
            {
                var ps = System.Management.Automation.PowerShell.Create();

                ps.Commands.AddScript("$verbosepreference='continue'; write-verbose 42");

                foreach ( var i in ps.Invoke<string>())
                {
                   Console.WriteLine("normal output: {0}" , i );   
                }
                foreach (var i in ps.Streams.Verbose)
                {
                    Console.WriteLine("verbose output: {0}" , i);
                }

            }
        }

        [Cmdlet("Get", "Colors")]
        public class GetColorsCommand : Cmdlet
        {
            protected override void ProcessRecord()
            {
                this.WriteObject("Red");
                this.WriteVerbose("r");
                this.WriteObject("Green");
                this.WriteVerbose("g");
                this.WriteObject("Blue");
                this.WriteVerbose("b");

            }

        }
    }

Der obige Code generiert diese Ausgabe:

d:\DemoCmdLet1\DemoCmdLet1>bin\Debug\DemoCmdLet1.exe
verbose output: 42
AKTUALISIERUNG AM 16.01.2010

Mithilfe der Powershell-Klasse (in System.Management.Automation, jedoch nur in der Version der Assembly, die mit dem Powershell 2.0-SDK geliefert wird, und nicht in der Standardversion unter Windows 7) kann ich das Cmdlet und programmgesteuert aufrufen Holen Sie sich die ausführliche Ausgabe. Der verbleibende Teil besteht darin, dieser Powershell-Instanz tatsächlich ein benutzerdefiniertes Cmdlet hinzuzufügen - da dies mein ursprüngliches Ziel war -, um meine Cmdlets und nicht die mit Powershell gelieferten zu testen.

class Program
{
    static void Main(string[] args)
    {
        var ps = System.Management.Automation.PowerShell.Create();
        ps.AddCommand("Get-Process");
        ps.AddParameter("Verbose");
        ps.Streams.Verbose.DataAdded += Verbose_DataAdded;
        foreach (PSObject result in ps.Invoke())
        {
            Console.WriteLine(
                    "output: {0,-24}{1}",
                    result.Members["ProcessName"].Value,
                    result.Members["Id"].Value);
        } 
        Console.ReadKey();
    }

    static void Verbose_DataAdded(object sender, DataAddedEventArgs e)
    {
        Console.WriteLine( "verbose output: {0}", e.Index);
    }
}


[Cmdlet("Get", "Colors")]
public class GetColorsCommand : Cmdlet
{
    protected override void ProcessRecord()
    {
        this.WriteObject("Hello");
        this.WriteVerbose("World");
    }
}

Antworten auf die Frage(2)

Ihre Antwort auf die Frage