2011-06-07 15 views
12


Estoy intentando crear un cmdlet en C#. El código es como la siguiente:PowerShell - Cómo importar-Módulo en un espacio de ejecución

[Cmdlet(VerbsCommon.Get, "HeapSummary")] 
public class Get_HeapSummary : Cmdlet 
{ 
    protected override void ProcessRecord() 
    { 
     RunspaceConfiguration config = RunspaceConfiguration.Create(); 
     Runspace myRs = RunspaceFactory.CreateRunspace(config); 
     myRs.Open(); 

     RunspaceInvoke scriptInvoker = new RunspaceInvoke(myRs); 
     scriptInvoker.Invoke("Set-ExecutionPolicy Unrestricted"); 

     Pipeline pipeline = myRs.CreatePipeline(); 
     pipeline.Commands.Add(@"Import-Module G:\PowerShell\PowerDbg.psm1"); 
     //... 
     pipeline.Invoke(); 

     Collection<PSObject> psObjects = pipeline.Invoke(); 
     foreach (var psObject in psObjects) 
     { 
      WriteObject(psObject); 
     } 
    } 
} 

Pero intentar ejecutar este cmdlet de PowerShell me da este error: El término módulo de importación no se reconoce como el nombre de un cmdlet. El mismo comando en PowerShell no me da este error. Si, en cambio, ejecuto 'Get-Command', puedo ver que 'Invoke-Module' aparece como CmdLet.

¿Hay alguna manera de hacer un 'Import-Module' en un Runspace?

Gracias!

Respuesta

18

Existen dos formas de importar módulos de forma programática, pero antes abordaré su método. Su línea pipeline.Commands.Add("...") solo debe agregar el comando, no el comando Y el parámetro. Se añade el parámetro por separado:

# argument is a positional parameter 
pipeline.Commands.Add("Import-Module"); 
var command = pipeline.Commands[0]; 
command.Parameters.Add("Name", @"G:\PowerShell\PowerDbg.psm1") 

El API tubería de arriba es un poco torpe de usar y está en desuso informalmente para muchos usos, aunque es en la base de muchas de las API de nivel superior. La mejor manera de hacer esto en powershell v2 o superior es mediante el uso de la System.Management.Automation.PowerShell Tipo y su API de fluidez:

# if Create() is invoked, a runspace is created for you 
var ps = PowerShell.Create(myRS); 
ps.Commands.AddCommand("Import-Module").AddArgument(@"g:\...\PowerDbg.psm1") 
ps.Invoke() 

Otra forma cuando se utiliza el último método es para precargar los módulos usando InitialSessionState, lo que evita la necesidad de sembrar el espacio de ejecución explícitamente con Import-Module. Ver mi blog aquí en cómo hacerlo:

http://nivot.org/nivot2/post/2010/05/03/PowerShell20DeveloperEssentials1InitializingARunspaceWithAModule.aspx

http://nivot.org/blog/post/2010/05/03/PowerShell20DeveloperEssentials1InitializingARunspaceWithAModule

Espero que esto ayude.

+2

Gracias! Pero el método Add() devuelve vacío. Supongo que necesita usar un objeto Command y agregarle un parámetro y pasarlo al método Add. Estás hablando de dos maneras de hacerlo programáticamente, ¿cuál es la segunda manera? – Absolom

+0

oops, respuesta actualizada con la segunda forma. – x0n

+0

También descubrí que si obtiene la excepción "Error de comprobación de AuthorizationManager" cuando intenta importar su módulo, asegúrese de que su archivo .psm1 esté guardado en UTF8 y no en ASCII. – Absolom

Cuestiones relacionadas