我有一个用C#编写的外部dll,我从程序集文档中研究了它使用Console.WriteLine
将其调试消息写入控制台。
这个DLL在我与应用程序的UI交互期间写入控制台,所以我不直接进行DLL调用,但我会捕获所有控制台输出,所以我想我必须在表单加载中初始化,然后得到稍后拍摄的文字。
我想将所有输出重定向到字符串变量。
我尝试了Console.SetOut
,但是使用它来重定向到字符串并不容易。
答案 0 :(得分:23)
由于您似乎希望实时捕获控制台输出,我发现您可能会创建自己的TextWriter
实施,只要发生Write
或WriteLine
,就会触发事件在Console
。
作者看起来像这样:
public class ConsoleWriterEventArgs : EventArgs
{
public string Value { get; private set; }
public ConsoleWriterEventArgs(string value)
{
Value = value;
}
}
public class ConsoleWriter : TextWriter
{
public override Encoding Encoding { get { return Encoding.UTF8; } }
public override void Write(string value)
{
if (WriteEvent != null) WriteEvent(this, new ConsoleWriterEventArgs(value));
base.Write(value);
}
public override void WriteLine(string value)
{
if (WriteLineEvent != null) WriteLineEvent(this, new ConsoleWriterEventArgs(value));
base.WriteLine(value);
}
public event EventHandler<ConsoleWriterEventArgs> WriteEvent;
public event EventHandler<ConsoleWriterEventArgs> WriteLineEvent;
}
如果它是WinForm应用程序,您可以设置编写器并在Program.cs中使用它的事件,如下所示:
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
using (var consoleWriter = new ConsoleWriter())
{
consoleWriter.WriteEvent += consoleWriter_WriteEvent;
consoleWriter.WriteLineEvent += consoleWriter_WriteLineEvent;
Console.SetOut(consoleWriter);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
static void consoleWriter_WriteLineEvent(object sender, Program.ConsoleWriterEventArgs e)
{
MessageBox.Show(e.Value, "WriteLine");
}
static void consoleWriter_WriteEvent(object sender, Program.ConsoleWriterEventArgs e)
{
MessageBox.Show(e.Value, "Write");
}
答案 1 :(得分:20)
它基本上等于以下内容:
var originalConsoleOut = Console.Out; // preserve the original stream
using(var writer = new StringWriter())
{
Console.SetOut(writer);
Console.WriteLine("some stuff"); // or make your DLL calls :)
writer.Flush(); // when you're done, make sure everything is written out
var myString = writer.GetStringBuilder().ToString();
}
Console.SetOut(originalConsoleOut); // restore Console.Out
因此,在您的情况下,您需要在调用第三方DLL之前进行设置。
答案 2 :(得分:2)
或者你可以将它包装在一个帮助器方法中,该方法将一些代码作为参数运行并返回打印的字符串。请注意我们如何优雅地处理异常。
public string RunCodeReturnConsoleOut(Action code)
{
string result;
var originalConsoleOut = Console.Out;
try
{
using (var writer = new StringWriter())
{
Console.SetOut(writer);
code();
writer.Flush();
result = writer.GetStringBuilder().ToString();
}
return result;
}
finally
{
Console.SetOut(originalConsoleOut);
}
}
答案 3 :(得分:0)
您也可以使用Console.OpenStandardOutput调用SetOut,这将恢复原始输出流:
Console.SetOut(new StreamWriter(Console.OpenStandardOutput()));
答案 4 :(得分:0)
使用 @Adam Lear 和 @Carlo V. Dango 提出的解决方案,我创建了一个辅助类:
public sealed class RedirectConsole : IDisposable
{
private readonly Action<string> logFunction;
private readonly TextWriter oldOut = Console.Out;
private readonly StringWriter sw = new StringWriter();
public RedirectConsole(Action<string> logFunction)
{
this.logFunction = logFunction;
Console.SetOut(sw);
}
public void Dispose()
{
Console.SetOut(oldOut);
sw.Flush();
logFunction(sw.ToString());
sw.Dispose();
}
}
可以通过以下方式使用:
public static void MyWrite(string str)
{
// print console output to Log/Socket/File
}
public static void Main()
{
using(var r = new RedirectConsole(MyWrite)) {
Console.WriteLine("Message 1");
Console.WriteLine("Message 2");
}
// After the using section is finished,
// MyWrite will be called once with a string containing all messages,
// which has been written during the using section,
// separated by new line characters
}