PowerShell通过C#控制台输出不同

7

我对C#比较新,但对PowerShell并不陌生。

我想使用C#来执行PowerShell代码。但是,对象的输出结果与在PowerShell窗口中运行命令时不同。我得到的是对象的名称而不是它的数据。这是我的尝试:

string script = @"
    get-process | ft
";

PowerShell powerShell = PowerShell.Create();

powerShell.AddScript(script);
var results = powerShell.Invoke();
foreach (var item in results)
{
    Console.WriteLine(item);
}

返回结果:

Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData

但是在PowerShell命令行窗口中,它返回一个更格式化的表格视图:

PS C:\Dropbox\PowerShell> ps | ft

Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id SI ProcessName ------- ------ ----- ----- ----- ------ -- -- ----------- 131 12 1980 2572 85 0.45 13216 1 acrotray

我真的想要两件事:

  1. 能够产生与PowerShell命令窗口相同的输出的代码
  2. 对正在发生的事情进行解释,以便我可以更好地导航

提前感谢!


1
可能是 https://dev59.com/xWAf5IYBdhLWcg3wbCN3 的重复问题。 - RobSiklos
2个回答

6
我找到了答案,感谢codeproject上的一个代码例子。我发现所有命令的末尾都需要添加“out-string”命令。所以要添加的额外代码是:

ps.AddCommand("Out-String");

我不知道控制台是否只是这样做,还是有更多的内容。

我认为主机正在执行这个操作(所以无论是控制台主机还是ISE主机,都是它的一部分功能)。当你在C#中使用一个runspace时,默认情况下不会发生这种情况,所以你现在所做的是可以的,或者你可以让你的应用程序成为一个完整的主机并在其中实现它。 - briantist
PowerShell引擎会将任何未经声明的对象隐式管道传输到“Out-Default”命令,而“Out-Default”会将它们转换为主机上的文本。 - user4003407

0

PowerShell使用自己的XML格式文档在控制台和ISE中返回表格样式输出。在您的情况下,Out-String是这种格式化发挥作用的地方,因为它将保留格式(您可以使用'-Stream'开关与out string一起使用,以返回每行执行的内容)。

可以从传回C#的对象中提取信息而不使用out-string;然而,根据我的经验,如果您只是显示此信息,则最好的选择是返回字符串。但是,如果您需要对对象进行其他处理,则可以返回对象,然后根据您正在处理的对象类型执行条件语句。例如,如果我需要在从PowerShell返回对象后操作对象(不使用'out-string'),则使用以下内容:

System.Diagnostic.Process是从Get-Process命令返回的对象类型-确保您确切地知道要传回C#的对象类型

using (PowerShell psRunspace = PowerShell.Create())
        {
            psRunspace.AddCommand("Get-Process");
            psRunspace.AddParameter("ComputerName", computerName);

            Collection<PSObject> outputObj = psRunspace.Invoke();

            foreach (PSObject obj in outputObj)
            {
                var objProperties = obj.Properties;
                var objMethods = obj.Methods;
                var baseObj = obj.BaseObject;

                if (baseObj is System.Diagnostic.Process) 
                {
                    var p = (System.Diagnostic.Process)baseObj;
                    //you can now access all members of this object normally
                    //Do something here with p.Properties or p.Methods etc...
                }
            }

我还建议,因为我在你的问题中没有看到它,考虑使用“using”语句来执行你的PowerShell命令。这将为你打开和关闭管道/运行空间。在你的例子中,除非你只是从你的示例代码中省略了它,否则似乎你没有关闭那个管道。此外,在调用命令时要具体说明你使用适当类型的对象,并像上面显示的那样使用一个集合来返回对象的类型(PSObject)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接