2009-07-18 20 views
8

Antecedentes

  • estoy usando PowerShell 2.0 en Windows 7.
  • Estoy escribiendo un cmdlet en un módulo de PowerShell ("módulo "es nuevo para Powershell 2.0).
  • Para probar el cmdlet, estoy escribiendo Pruebas unitarias en Visual Studio 2008 que invocan mediante programación el cmdlet.

REFERENCIA

  • This Article on MSDN llamado "Cómo invocar un cmdlet desde dentro de un cmdlet" muestra cómo llamar a un cmdlet de C#.

CÓDIGO FUENTE

  • Ésta es una versión destilada de mi código real — que hemos hecho lo más pequeño posible para que pueda ver el problema que estoy teniendo con claridad:Cómo capturar salida detallada de una PowerShell cmdlet cuando el cmdlet se invoca mediante programación de C#

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

COMENTARIOS

  • Entiendo cómo habilitar y capturar resultados detallados desde la línea de comandos de Powershell; ese no es el problema.
  • En este caso, invoco mediante programación el cmdlet de C#.
  • Nada de lo que he encontrado aborda mi situación específica. Algunos artículos sugieren que debo implementar mi propio PSHost, pero me parece caro y también me parece que tengo que llamar el cmdlet como texto, lo cual me gustaría evitar porque no está tan tipado.

ACTUALIZACIÓN EN 2009-07-20

Aquí está el código fuente basado en la respuesta a continuación.

Algunas cosas todavía no están claras para mí: * ¿Cómo llamar los "Get-Colores" cmdlet (a ser posible sin tener que pasarlo como una cadena en el objet ps) * ¿Cómo obtener la salida detallada como se genera en lugar de obtener una colección de ellos al final.

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

      } 

     } 
    } 

El código anterior genera esta salida:

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

ACTUALIZACIÓN SOBRE 2010-01-16

utilizando la clase Powershell (que se encuentra en System.Management.Automation pero sólo en la versión del ensamblado que viene con el SDK de powershell 2.0, no lo que viene de fábrica en Windows 7) Puedo llamar al cmdlet mediante programación y obtener la salida detallada. La parte restante es agregar un cmdlet personalizado a esa instancia de PowerShell, porque ese era mi objetivo original, probar mis cmdlets de forma individual, no aquellos que vienen con PowerShell.

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"); 
    } 
} 
+1

faltaba un backtick 'en mi respuesta, esto evita que la variable $ verbosepreference se evalúe con anticipación. – x0n

+0

¿Por qué no marcó mi respuesta como la respuesta? – x0n

+0

Si desea registros detallados en tiempo real, suscríbase al evento datachanged en la propiedad streams de la instancia de powershell. – x0n

Respuesta

10
  • Salida detallada no es en realidad la salida a menos $VerbosePreference se fija al menos a "Continuar".
  • Uso del tipo PowerShell para ejecutar su cmdlet, y leyó VerboseRecord instancias de la Streams.Verbose Propery

Ejemplo de script de PowerShell:

ps> $ps = [powershell]::create() 
ps> $ps.Commands.AddScript("`$verbosepreference='continue'; write-verbose 42") 
ps> $ps.invoke() 
ps> $ps.streams.verbose 
Message InvocationInfo       PipelineIterationInfo 
------- --------------       --------------------- 
42  System.Management.Automation.Invocat... {0, 0} 

Esto debería ser fácil de traducir en C#.

0
1.  string scriptFile = "Test.ps1"; 
2.  using (PowerShell ps = PowerShell.Create()) 
3.  { 
4.   const string getverbose = "$verbosepreference='continue'"; 
5.   ps.AddScript(string.Format(getverbose)); 
6.   ps.Invoke(); 
7.   ps.Commands.Clear(); 
8.   ps.AddScript(@".\" + scriptFile); 
9.   ps.Invoke(); 
10.   foreach (var v in ps.Streams.Verbose) 
11.   { 
12.    Console.WriteLine(v.Message); 
13.   } 
14.  } 

Las líneas importantes son la línea 5 y 6. Esto básicamente configura la $ verbosepreference para la sesión y para los próximos nuevos comandos y scripts.

Cuestiones relacionadas