简体   繁体   English

将powershell cmdlet输出写入文件,而不是从c#写入管道

[英]write powershell cmdlet output to a file instead of writing to pipeline from c#

I am trying to implement a powershell cmdlet in C#. 我正在尝试在C#中实现Powershell cmdlet。

I have an object in the code something like. 我在代码中有一个类似的对象。

class A{
    string Title_p;
    string Title_q;
    int Title_r;
    string[] Title_s;
}

So, in the cmdlet implementation, when I give this.WriteObject(A_obj) , it converts the object data into beautiful readable table format with column titles as object names. 因此,在cmdlet实现中,当我提供this.WriteObject(A_obj) ,它将对象数据转换为具有列标题作为对象名称的漂亮可读表格式。 Something like below: 如下所示:

Title_p   Title_q  Title_r  Title_s
=======   =======  =======  =======
Hello      Bolo     12     {RR,TT,YY}

But all this output is redirected to the pipeline where the final cmdlet will be fired from. 但是,所有这些输出都将重定向到将从中触发最终cmdlet的管道。

But I also want to log all this output to a file (besides printing to pipeline) 但我也想将所有这些输出记录到文件中(除了打印到管道之外)

I am aware that I can give CmdLet-Sud | out-file c:/data.txt 我知道我可以给CmdLet-Sud | out-file c:/data.txt CmdLet-Sud | out-file c:/data.txt . CmdLet-Sud | out-file c:/data.txt But I don't want this. 但我不要这个。 I want to just fire the command CmdLet-Sud , and it should print the data to pipeline as well as to a file. 我只想触发命令CmdLet-Sud ,它应该将数据打印到管道以及文件中。

So, how to convert the object into such a printable table format? 那么,如何将对象转换为可打印的表格格式呢?

You can create a "Powershell" in your C# code (using System.Management.Automation.Powershell). 您可以在C#代码中创建一个“ Powershell”(使用System.Management.Automation.Powershell)。 Your "Powershell" (bad choice of class names IMO, I'll call it SMA.Powershell in this answer for clarity) can invoke tee-object (or append-content or set-content ). 您的“ Powershell”(类名称IMO的错误选择,为清楚起见,在本答案中将其称为SMA.Powershell)可以调用tee-object (或append-contentset-content )。 You can then pass your class instance(s) as arguments to the SMA.Powershell. 然后,您可以将您的类实例作为参数传递给SMA.Powershell。

Alternatively you can just use classes under the System.IO file space and write the file directly. 或者,您可以只使用System.IO文件空间下的类并直接写入文件。 You can separately write the same output via write-object. 您可以通过write-object分别写入相同的输出。

BTW, writing the output to a file doesn't make sense unless you have support for serialization and deserialization in your class. 顺便说一句,将输出写入文件是没有意义的,除非您在类中支持序列化和反序列化。 Unless, what you really want is to write your class instance as a textual table. 除非,您真正想要的是将类实例编写为文本表。 In which case your SMA.Powershell can be something like % { $_ | ft | set-content c:\\data.txt; $_} 在这种情况下,您的SMA.Powershell可能类似于% { $_ | ft | set-content c:\\data.txt; $_} % { $_ | ft | set-content c:\\data.txt; $_} % { $_ | ft | set-content c:\\data.txt; $_} . % { $_ | ft | set-content c:\\data.txt; $_}

Tee-Object did the work for me. Tee-Object为我完成了工作。

PowerShell powerShellInstance = PowerShell.Create();
powerShellInstance.AddCommand("Tee-Object");
powerShellInstance.AddParameter("FilePath", filePath);
powerShellInstance.AddParameter("InputObject", obj_A);
powerShellInstance.AddParameter("Append");
powerShellInstance.Invoke();

But, when the above code is invoked multiple times, the file is written as 但是,当多次调用上述代码时,该文件将写为

Title_p   Title_q  Title_r  Title_s
=======   =======  =======  =======
Hello      Bolo     12     {RR,TT,YY}

Title_p   Title_q  Title_r  Title_s
=======   =======  =======  =======
Aaaao      Colo     13     {EE,YY}

Title_p   Title_q  Title_r  Title_s
=======   =======  =======  =======
HHSAR      Dolo     14     {QQ,XX}

But in cmdlet implementation, even though you call this.WriteObject() multiple times with multiple objects, the result would be as 但是在cmdlet实现中,即使您多次使用多个对象调用this.WriteObject(),结果也将是

Title_p   Title_q  Title_r  Title_s
=======   =======  =======  =======
Hello      Bolo     12     {RR,TT,YY}
Aaaao      Colo     13     {EE,YY}
HHSAR      Dolo     14     {QQ,XX}

I am trying to see if I can tweak the code such that even the invoke() command is called multiple times in a program, the output file would still have only only one column header instead of one column header for each object (in the final output file) 我正在尝试查看是否可以调整代码,以便即使在程序中多次调用invoke()命令,输出文件仍将仅具有一个列标题,而不是每个对象一个列标题(最终输出文件)

Finally done, with want I wanted: 终于完成了,我想要:

// When this method is called for the first time, it creates a table header too.
// The following is the PowerShell line that will be run in the runspace.
// Write-Output -InputObject <object_A> | Format-Table | Out-String

// For the next time, when this routine is called, the following gets executed.
// Write-Output -InputObject <object_A> | Format-Table -HideTableHeaders | Out-String

Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
Pipeline pipeLine = runspace.CreatePipeline();

Command command1 = new Command("Write-Output");
command1.Parameters.Add("InputObject", object_A);

Command command2 = new Command("Format-Table");
if (this.filePath != null)
{
    // If this is not the first row, hide the table headers
    command2.Parameters.Add("HideTableHeaders");
}
Command command3 = new Command("Out-String");

pipeLine.Commands.Add(command1);
pipeLine.Commands.Add(command2);
pipeLine.Commands.Add(command3);
var results = pipeLine.Invoke();

// The resultant text from the command will have a lot of white spaces/carriage returns.
// So, let us trim the content before adding it to file.
foreach (var result in results)
{
    string data = null;
    data = string.Concat(result);
    data = data.Trim();

    // For the first time, we need to create a log file too.
    if (filePath == null)
    {
        // Call custom routine CreateLogFile() which creates a file and returns the file path as string for you
        filePath = CreateLogFile();
    }

    // Write the object row into the file.
    using (StreamWriter writer = System.IO.File.AppendText(this.filePath))
    {
        writer.WriteLine(data);
    }
}

runspace.Close();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM