将 powershell cmdlet 输出写入文件而不是从 c# 写入管道
write powershell cmdlet output to a file instead of writing to pipeline from c#
我正在尝试在 C# 中实现 powershell cmdlet。
我在代码中有一个 object 类似的东西。
class A{
string Title_p;
string Title_q;
int Title_r;
string[] Title_s;
}
因此,在 cmdlet 实现中,当我给出 this.WriteObject(A_obj)
时,它将 object 数据转换为美观易读的 table 格式,列标题为 object 名称。如下所示:
Title_p Title_q Title_r Title_s
======= ======= ======= =======
Hello Bolo 12 {RR,TT,YY}
但是所有这些输出都被重定向到将从中触发最终 cmdlet 的管道。
但我还想将所有这些输出记录到一个文件中(除了打印到管道外)
我知道我可以给 CmdLet-Sud | out-file c:/data.txt
。但我不想要这个。我只想触发命令 CmdLet-Sud
,它应该将数据打印到管道和文件中。
那么,如何将object转换成这样的printabletable格式呢?
您可以在 C# 代码中创建 "Powershell"(使用 System.Management.Automation.Powershell)。您的 "Powershell"(class 名称 IMO 的错误选择,为了清楚起见,我将在此答案中将其称为 SMA.Powershell)可以调用 tee-object
(或 append-content
或 set-content
).然后,您可以将 class 个实例作为参数传递给 SMA.Powershell。
或者你可以只使用 System.IO 文件 space 下的 classes 并直接写入文件。您可以通过 write-object 单独写入相同的输出。
顺便说一句,将输出写入文件没有任何意义,除非您在 class 中支持序列化和反序列化。除非,您真正想要的是将 class 实例写成文本 table。在这种情况下,您的 SMA.Powershell 可以是 % { $_ | ft | set-content c:\data.txt; $_}
.
Tee-Object 为我完成了工作。
PowerShell powerShellInstance = PowerShell.Create();
powerShellInstance.AddCommand("Tee-Object");
powerShellInstance.AddParameter("FilePath", filePath);
powerShellInstance.AddParameter("InputObject", obj_A);
powerShellInstance.AddParameter("Append");
powerShellInstance.Invoke();
但是,当上面的代码被多次调用时,文件写成
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}
但是在 cmdlet 实现中,即使您使用多个 object 多次调用 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}
我想看看是否可以调整代码,即使在程序中多次调用 invoke() 命令,输出文件仍然只有一列,而不是一列 header每个 object 列 header(在最终输出文件中)
终于完成了,我想要的:
// 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();
我正在尝试在 C# 中实现 powershell cmdlet。
我在代码中有一个 object 类似的东西。
class A{
string Title_p;
string Title_q;
int Title_r;
string[] Title_s;
}
因此,在 cmdlet 实现中,当我给出 this.WriteObject(A_obj)
时,它将 object 数据转换为美观易读的 table 格式,列标题为 object 名称。如下所示:
Title_p Title_q Title_r Title_s
======= ======= ======= =======
Hello Bolo 12 {RR,TT,YY}
但是所有这些输出都被重定向到将从中触发最终 cmdlet 的管道。
但我还想将所有这些输出记录到一个文件中(除了打印到管道外)
我知道我可以给 CmdLet-Sud | out-file c:/data.txt
。但我不想要这个。我只想触发命令 CmdLet-Sud
,它应该将数据打印到管道和文件中。
那么,如何将object转换成这样的printabletable格式呢?
您可以在 C# 代码中创建 "Powershell"(使用 System.Management.Automation.Powershell)。您的 "Powershell"(class 名称 IMO 的错误选择,为了清楚起见,我将在此答案中将其称为 SMA.Powershell)可以调用 tee-object
(或 append-content
或 set-content
).然后,您可以将 class 个实例作为参数传递给 SMA.Powershell。
或者你可以只使用 System.IO 文件 space 下的 classes 并直接写入文件。您可以通过 write-object 单独写入相同的输出。
顺便说一句,将输出写入文件没有任何意义,除非您在 class 中支持序列化和反序列化。除非,您真正想要的是将 class 实例写成文本 table。在这种情况下,您的 SMA.Powershell 可以是 % { $_ | ft | set-content c:\data.txt; $_}
.
Tee-Object 为我完成了工作。
PowerShell powerShellInstance = PowerShell.Create();
powerShellInstance.AddCommand("Tee-Object");
powerShellInstance.AddParameter("FilePath", filePath);
powerShellInstance.AddParameter("InputObject", obj_A);
powerShellInstance.AddParameter("Append");
powerShellInstance.Invoke();
但是,当上面的代码被多次调用时,文件写成
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}
但是在 cmdlet 实现中,即使您使用多个 object 多次调用 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}
我想看看是否可以调整代码,即使在程序中多次调用 invoke() 命令,输出文件仍然只有一列,而不是一列 header每个 object 列 header(在最终输出文件中)
终于完成了,我想要的:
// 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();