如何捕获Powershell CmdLet';以编程方式从C调用CmdLet时的详细输出# 背景 我正在Windows 7上使用Powershell 2.0 我正在Powershell模块中编写cmdlet(“模块”是Powershell 2.0的新版本) 为了测试cmdlet,我正在VisualStudio2008中编写单元测试,以编程方式调用cmdlet 参考文献 名为“如何从Cmdlet中调用Cmdlet”的演示了如何从C#调用Cmdlet 源代码
这是我实际代码的一个提炼版本-我将其尽可能小,以便您可以清楚地看到我遇到的问题:如何捕获Powershell CmdLet';以编程方式从C调用CmdLet时的详细输出# 背景 我正在Windows 7上使用Powershell 2.0 我正在Powershell模块中编写cmdlet(“模块”是Powershell 2.0的新版本) 为了测试cmdlet,我正在VisualStudio2008中编写单元测试,以编程方式调用cmdlet 参考文献 名为“如何从Cmdlet中调用Cmdlet”的演示了如何从C#调用Cmdlet 源代码,c#,powershell,powershell-2.0,cmdlet,C#,Powershell,Powershell 2.0,Cmdlet,这是我实际代码的一个提炼版本-我将其尽可能小,以便您可以清楚地看到我遇到的问题: using System; using System.Management.Automation; namespace DemoCmdLet1 { class Program { static void Main(string[] args) { var cmd = new GetColorsCommand();
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");
}
}
}
2010-01-16更新
通过使用Powershell类(可在System.Management.Automation中找到,但仅在Powershell 2.0 SDK附带的程序集版本中找到,而不是Windows 7上的现成版本),我可以通过编程方式调用cmdlet并获得详细输出。剩下的部分是向该powershell实例实际添加一个自定义cmdlet—因为这是我的原始目标—以单元测试我的cmdlet,而不是powershell附带的cmdlet
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");
}
}
- 除非至少将
设置为“Continue”,否则详细输出不会实际输出$VerbosePreference
- 使用PowerShell类型运行
,并从cmdlet
属性中读取Streams.Verbose
实例VerboseRecord
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}
这应该很容易翻译成C
重要的一行是第5行和第6行。这基本上为会话以及即将发布的新命令和脚本设置了$verbosepreference。我的答案中缺少了一个backtick`标记-这会阻止$verbosepreference变量提前计算。为什么不将我的回答标记为答案?如果需要实时详细记录,订阅powershell实例的streams属性上的datachanged事件。我已升级该问题以说明您提供的新信息。我仍然无法回答此问题,因为我还不知道如何将“Get-Colors”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");
}
}
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}
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. }