【问题标题】:redirecting output from an external dll in powershell在powershell中重定向来自外部dll的输出
【发布时间】:2016-01-11 16:42:59
【问题描述】:

我有一个 C# 程序集,它处理一个 xml 文件,最后将结果输出到控制台。
例如Console.WriteLine(_header.ToString());
我可以在 powershell 中加载这个 dll 并像这样调用正确的方法:

[sqlproj_doctor.sqlprojDoctor]::ProcessXML($file) | out-file ./test.xml

一切都好。

当我想重定向输出时,问题就开始了。出于某种原因,标准输出为空。我错过了什么?我需要进一步处理这个 dll 的输出。

注意:如果我将相同的代码编译为可执行文件,它会正确填充标准输出流,并且我可以重定向输出。

另一个注意事项:作为一种解决方法,我将方法从 void 更改为 string,现在可以操作返回的字符串。

【问题讨论】:

  • 它真的使用Console.WriteLine而不是其他东西在控制台上显示文本吗?
  • 我粘贴了类库中使用的确切代码行...
  • 感谢 Mathias,但您参考的文章描述了如何拦截标准输出流。就我而言,标准输出是空的。那就是问题所在。另外,让我们注意上下文。在您的示例中,一切都发生在一个应用程序中。在我的情况下,正在加载一个 dll 并从 powershell 控制台调用一个方法。
  • @MorDeror 你能说明一下,你是如何尝试重定向输出的?如果ProcessXML 只使用Console.WriteLine,那么 Mathias R. Jessen 提出的方法应该适合你。如果你自己有汇编代码,如下你的注释我改变了方法,为什么不重写方法来接受TextWriter来写而不是使用Console.WriteLine

标签: c# powershell dll


【解决方案1】:

当您调用 [Console]::WriteLine('SomeText') 时,它会写入 PowerShell 进程标准输出,而不是命令输出,因此它无法通过标准 PowerShell 运算符从同一 PowerShell 进程内部重定向,如下所示:

[Console]::WriteLine('SomeText')|Out-File Test.txt

您必须生成新的 PowerShell 进程,并重定向该新进程的输出:

powershell -Command "[Console]::WriteLine('SomeText')"|Out-File Test.txt

如果某些命令使用[Console]::WriteLine 写入控制台,您可以在不启动新的 PowerShell 实例的情况下捕获该输出:

$OldConsoleOut=[Console]::Out
$StringWriter=New-Object IO.StringWriter
[Console]::SetOut($StringWriter)

[Console]::WriteLine('SomeText') # That command will not print on console.

[Console]::SetOut($OldConsoleOut)
$Results=$StringWriter.ToString()
$Results # That variable would contain "SomeText" text.

虽然如果命令不使用[Console]::WriteLine这没有帮助,但直接写入标准输出流:

$OldConsoleOut=[Console]::Out
$StringWriter=New-Object IO.StringWriter
[Console]::SetOut($StringWriter)

$Stdout=[Console]::OpenStandardOutput()
$Bytes=[Console]::OutputEncoding.GetBytes("SomeText"+[Environment]::NewLine)
$Stdout.Write($Bytes,0,$Bytes.Length) # That command will print on console.
$Stdout.Close()

[Console]::SetOut($OldConsoleOut)
$Results=$StringWriter.ToString()
$Results # That variable will be empty.

【讨论】:

  • 有趣。感谢您通过示例进行详尽的解释。我能够将输出捕获到字符串编写器。那么,这里的问题是我的程序的标准输出和我的重定向管道的标准输入在不同的上下文中吗?这就是为什么将所有标准输出重定向到字符串编写器的原因,因为无论它发生在什么执行上下文中,所有输出都被转储到那里?
  • @MorDeror 当您调用外部 dll 时,它不会使用自己的标准输出创建外部进程来捕获。它在 PowerShell 进程中工作。从 PowerShell 的角度来看,.NET 方法没有标准输出(PowerShell 有自己的基于对象的管道,它不会尝试识别对控制台的任何写入),它们只有返回值。 [Console]::SetOut 技巧只在进程内部起作用,并且只有当你以某种方式使用 [Console]::Out 时。例如,PowerShell 本身写入控制台真正的 WinAPI,因此不受[Console]::SetOut 的影响。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-11
  • 2015-03-16
  • 2015-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-11
相关资源
最近更新 更多