我試圖顯示在C#程序中的文本框中的DLL中的方法的控制檯輸出(cout)。每次我調用該方法時,控制檯輸出都將顯示在Visual Studio的輸出窗格中。有沒有辦法將輸出窗格的內容重定向到文本框?重定向cout從c + + dll到C#中的文本框#
該DLL是由其他人在C++寫的,我無法控制它的改變。 該DLL使用SWIG打包,以便可以通過我的C#代碼進行調用。
我試圖顯示在C#程序中的文本框中的DLL中的方法的控制檯輸出(cout)。每次我調用該方法時,控制檯輸出都將顯示在Visual Studio的輸出窗格中。有沒有辦法將輸出窗格的內容重定向到文本框?重定向cout從c + + dll到C#中的文本框#
該DLL是由其他人在C++寫的,我無法控制它的改變。 該DLL使用SWIG打包,以便可以通過我的C#代碼進行調用。
在遵循David建議的鏈接之後,我決定爲您的問題寫一個更具體的解決方案。該版本允許您通過BackgroundWorker
PropertyChangedEventHandler
回撥在GUI中接收標準輸出。
下面是該ConsoleRedirector代碼:
public class ConsoleRedirector : IDisposable
{
private static ConsoleRedirector _instance;
public static void attach(ProgressChangedEventHandler handler, bool forceConsoleRedirection)
{
Debug.Assert(null == _instance);
_instance = new ConsoleRedirector(handler, forceConsoleRedirection);
}
public static void detatch()
{
_instance.Dispose();
_instance = null;
}
public static bool isAttached
{
get
{
return null != _instance;
}
}
private static void ResetConsoleOutStream()
{
//Force console to recreate its output stream the next time Write/WriteLine is called
typeof(Console).GetField("_out", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).SetValue(null, null);
}
private const int PERIOD = 500;
private const int BUFFER_SIZE = 4096;
private volatile bool _isDisposed;
private BackgroundWorker _worker;
private readonly IntPtr _stdout;
private readonly Mutex _sync;
private readonly System.Threading.Timer _timer;
private readonly char[] _buffer;
private readonly AnonymousPipeServerStream _outServer;
private readonly TextReader _outClient;
private readonly bool _forceConsoleRedirection;
private StreamWriter _consoleStandardOut;
private ConsoleRedirector(ProgressChangedEventHandler handler, bool forceConsoleRedirection)
{
bool ret;
_forceConsoleRedirection = forceConsoleRedirection;
if (!_forceConsoleRedirection)
{
//Make sure Console._out is initialized before we redirect stdout, so the redirection won't affect it
TextWriter temp = Console.Out;
}
AnonymousPipeClientStream client;
_worker = new BackgroundWorker();
_worker.ProgressChanged += handler;
_worker.DoWork += _worker_DoWork;
_worker.WorkerReportsProgress = true;
_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
_sync = new Mutex();
_buffer = new char[BUFFER_SIZE];
_outServer = new AnonymousPipeServerStream(PipeDirection.Out);
client = new AnonymousPipeClientStream(PipeDirection.In, _outServer.ClientSafePipeHandle);
Debug.Assert(_outServer.IsConnected);
_outClient = new StreamReader(client, Encoding.Default);
ret = SetStdHandle(STD_OUTPUT_HANDLE, _outServer.SafePipeHandle.DangerousGetHandle());
Debug.Assert(ret);
if (_forceConsoleRedirection)
{
ResetConsoleOutStream(); //calls to Console.Write/WriteLine will now get made against the redirected stream
}
_worker.RunWorkerAsync(_outClient);
_timer = new System.Threading.Timer(flush, null, PERIOD, PERIOD);
}
void _worker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = (BackgroundWorker)sender;
TextReader client = (TextReader)e.Argument;
try
{
while (true)
{
int read = client.Read(_buffer, 0, BUFFER_SIZE);
if (read > 0)
worker.ReportProgress(0, new string(_buffer, 0, read));
}
}
catch (ObjectDisposedException)
{
// Pipe was closed... terminate
}
catch (Exception ex)
{
}
}
private void flush(object state)
{
_outServer.Flush();
}
public void Dispose()
{
Dispose(true);
}
~ConsoleRedirector()
{
Dispose(false);
}
private void Dispose(bool disposing)
{
if (!_isDisposed)
{
lock (_sync)
{
if (!_isDisposed)
{
_isDisposed = true;
_timer.Change(Timeout.Infinite, Timeout.Infinite);
_timer.Dispose();
flush(null);
try { SetStdHandle(STD_OUTPUT_HANDLE, _stdout);}
catch (Exception) { }
_outClient.Dispose();
_outServer.Dispose();
if (_forceConsoleRedirection)
{
ResetConsoleOutStream(); //Calls to Console.Write/WriteLine will now get redirected to the original stdout stream
}
}
}
}
}
private const int STD_OUTPUT_HANDLE = -11;
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetStdHandle(int nStdHandle, IntPtr hHandle);
[DllImport("kernel32.dll")]
private static extern IntPtr GetStdHandle(int nStdHandle);
}
下面是一個完整的示例形式的鏈接,演示瞭如何使用它:ConsoleRedirector Example Form
它的工作原理!非常感謝!! – 2012-01-31 05:40:33
+1優秀作品! – 2012-01-31 07:43:19
我一直在我的應用中使用這個輝煌的代碼,在Windows 7中工作得很好!當我升級到Windows 10時,這不再起作用。你有什麼想法,Windows 10可能破壞了上面的代碼? – bradcarman 2017-05-22 15:54:26
有一個看看這個:http://pastebin.com/f3eda7c8 – 2012-01-30 09:26:26