WinForm/WPF에서 Console 창을 띄워 출력하는 방법 (2) - Output 디버깅 출력을 AllocConsole로 우회
지난 글에서 Windows UI 응용 프로그램에서 Console 창을 띄워 사용하는 방법을 설명했습니다.
WinForm/WPF에서 Console 창을 띄워 출력하는 방법
; https://www.sysnet.pe.kr/2/0/12000
위의 구현은 2가지 문제가 있다고 했는데요, 1)
AllocConsole 이전에
Console.WriteLine을 호출하면 안 되고, 2) 비주얼 스튜디오가 F5 디버깅으로 실행한 경우에는 Output 창을 이용하므로 안 됩니다. 그런데 가만 생각해 보니 Output 창도 어차피 Console 출력을 우회한 것이기 때문에 관련 redirection을 잘 조절해 보면 방법이 있을 것 같습니다. 그리고, 실제로 찾아보니 다음과 같이 이미 구현 코드가 있군요. ^^
Console.Out Output is showing in Output Window, Needed in AllocConsole()
; https://stackoverflow.com/questions/41624103/console-out-output-is-showing-in-output-window-needed-in-allocconsole
이를 바탕으로 ConsoleOutRedirector 코드를 좀 더 다듬을 수 있고,
using Microsoft.Win32.SafeHandles;
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace WindowsFormsApp1
{
public class ConsoleOutRedirector : IDisposable
{
public ConsoleOutRedirector()
{
NativeMethods.AllocConsole();
InitConsole();
}
private void InitConsole()
{
IntPtr stdHandle = NativeMethods.CreateFile(
"CONOUT$",
NativeMethods.GENERIC_WRITE,
NativeMethods.FILE_SHARE_WRITE,
0, NativeMethods.OPEN_EXISTING, 0, 0
);
SafeFileHandle safeFileHandle = new SafeFileHandle(stdHandle, true);
FileStream fileStream = new FileStream(safeFileHandle, FileAccess.Write);
Encoding encoding = System.Text.Encoding.GetEncoding(NativeMethods.MY_CODE_PAGE);
StreamWriter standardOutput = new StreamWriter(fileStream, encoding);
standardOutput.AutoFlush = true;
Console.SetOut(standardOutput);
}
public void Dispose()
{
NativeMethods.FreeConsole();
}
}
static class NativeMethods
{
internal const int MY_CODE_PAGE = 437;
internal const uint GENERIC_WRITE = 0x40000000;
internal const uint FILE_SHARE_WRITE = 0x2;
internal const uint OPEN_EXISTING = 0x3;
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr CreateFile(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
uint lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
uint hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool AllocConsole();
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool FreeConsole();
}
}
사용은 다음과 같이 하면 됩니다.
using System;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
static class Program
{
[STAThread]
static void Main()
{
#if DEBUG
using (var consoleOutRedirector = new ConsoleOutRedirector())
#endif
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
}
그러면, F5와 Ctrl + F5 모두 정상적으로 콘솔 창이 뜨고 Console.Write 출력을 가져옵니다. 게다가 AllocConsole 이전에 Console.Write를 해도,
Console.WriteLine("TEST"); // 디버깅 시 Output 창에 출력
// 그 외에는 콘솔 창이 없으므로 누락
using (var consoleOutRedirector = new ConsoleOutRedirector())
{
Console.WriteLine("Shown in AllocConsole window"); // AllocConsole 창에 출력
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
정상적으로 AllocConsole 창에 출력이 됩니다.
이 글의 예제 코드는 다음의 github repo에 있습니다.
DotNetSamples/WinForms/ConsoleOutRedirect/
; https://github.com/stjeong/DotNetSamples/tree/master/WinForms/ConsoleOutRedirect
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]