ФОН
- Я использую Powershell 2.0 в Windows 7.
- Я пишу командлет в модуле Powershell («модуль» является новым для Powershell 2.0).
- Чтобы проверить командлет, который я пишу, модульные тесты в Visual Studio 2008, которые программно вызывают командлет.
ССЫЛКА
- В этой статье на MSDN под названием «Как вызвать командлет из командлета» показано, как вызвать командлет из C #.
ИСТОЧНИК КОД
Это искаженная версия моего фактического кода & mdash; Я сделал его как можно меньше, чтобы вы могли видеть проблему, с которой я столкнулся:
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");
}
}
}
КОММЕНТАРИИ
- Я понимаю, как включить и получить подробный вывод из командной строки Powershell; это не проблема.
- В этом случае я программно вызываю командлет из C #.
- Ничего из того, что я нашел, не соответствует моему конкретному сценарию. В некоторых статьях предлагается реализовать собственный PSHost, но он кажется дорогим, а также кажется, что нужно вызывать командлет как текст, чего я хотел бы избежать, поскольку он не так строго напечатан.
ОБНОВЛЕНИЕ НА 2009-07-20
Вот исходный код, основанный на ответе ниже.
Некоторые вещи до сих пор мне не ясны:
* Как вызвать командлет Get-Colors (в идеале, без необходимости передавать его в виде строки в объект ps)
* Как получить подробный вывод , как он генерируется вместо получения их коллекции в конце.
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");
}
}
}
Код выше генерирует этот вывод:
d:\DemoCmdLet1\DemoCmdLet1>bin\Debug\DemoCmdLet1.exe
verbose output: 42
ОБНОВЛЕНИЕ НА 2010-01-16
с помощью класса Powershell (находится в System.Management.Automation, но только в версии сборки, поставляемой с PowerShell 2.0 SDK, а не в стандартной версии для Windows 7), которую я могу вызвать программно командлет и получить подробный вывод. Остальная часть заключается в том, чтобы фактически добавить пользовательский командлет к этому экземпляру PowerShell - поскольку это было моей первоначальной целью - провести модульное тестирование моих командлетов, а не тех, которые поставляются с 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");
}
}