【发布时间】:2009-07-18 02:54:18
【问题描述】:
背景
- 我在 Windows 7 上使用 Powershell 2.0。
- 我正在 Powershell 模块中编写 cmdlet(“模块”是 Powershell 2.0 的新功能)。
- 为了测试 cmdlet,我正在 Visual Studio 2008 中编写单元测试,以编程方式调用 cmdlet。
参考
- This Article on MSDN 名为“如何从 Cmdlet 中调用 Cmdlet”,展示了如何从 C# 调用 cmdlet。
源代码
-
这是我的实际代码的提炼版本 - 我已将其尽可能小,以便您可以清楚地看到我遇到的问题:
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# 调用 cmdlet。
- 我发现没有任何东西可以解决我的具体情况。一些文章建议我应该实现自己的 PSHost,但似乎很昂贵,而且似乎必须将 cmdlet 作为文本调用,我想避免这种情况,因为它不是强类型的。
2009 年 7 月 20 日更新
这是基于以下答案的源代码。
有些事情我还不清楚: * 如何调用“Get-Colors”cmdlet(理想情况下不必将其作为字符串传递给 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 年 1 月 16 日更新
通过使用 Powershell 类(在 System.Management.Automation 中找到,但仅在 powershell 2.0 SDK 附带的程序集版本中,而不是在 Windows 7 上开箱即用的版本中)我可以以编程方式调用cmdlet 并获取详细输出。剩下的部分是实际添加一个自定义 cmdlet 到该 powershell 实例 - 因为这是我最初的目标 - 对我的 cmdlet 而不是 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");
}
}
【问题讨论】:
-
我的回答中缺少一个反引号 ` - 这可以防止 $verbosepreference 变量被提前评估。
-
您为什么没有将我的回复标记为答案?
-
如果您想要实时详细记录,请订阅 powershell 实例的流属性上的 datachanged 事件。
-
我已经更新了问题以说明您提供的新信息。我仍然不能说这个问题得到了回答,因为我还没有弄清楚如何将“Get-Colors”cmdlet 添加到 Powershell 实例。
-
您可能应该问一个新问题。当我回答您的问题时,您在旧问题中添加了一个新问题。
标签: c# powershell powershell-2.0 powershell-cmdlet