[.NET] 콘솔 애플리케이션(console application)에서 콘솔 모드 변경
별생각 없이 콘솔로 프로그램을 만들었는데....
기본적으로 있는 콘솔 모드들 때문에 이상한 동작을 하는 경우가 있습니다.
대표적인 것이 "빠른 편집 모드(Quick Edit Mode)"라는 것인데
콘솔 창을 클릭하거나 드레그하면 응용프로그램이 멈추는 현상입니다.
이 모드를 바꾸는 방법을 알아봅시다.
1. WinApi를 사용해야 한다.
몇 가지 방법들이 있지만 결국은 WinApi를 이용하는 것이 가장 편합니다.
WinApi로 콘솔 모드를 변경하려면
1) 디바이스(여기서는 콘솔)의 핸들을 받아서
2) 콘솔 모드 설정값을 받아온 뒤
3) 받은 설정값이 원하는 설정을 추가(혹은 제거)하고
4) 콘솔 모드 설정값을 다시 설정합니다.
설정값이 uint(UInt32)로 된 플래그(flag) 값이라 비트연산으로 추가나 제거를 할 수 잇습니다.
(참고 : [.NET] 열거형 맴버(enum)의 플래그(Flags)와 비트(bit) 연산)
2. 설정값 바꾸기
이제 코드를 한번 짜봅시다.
먼저 WinAPI를 임포트해야 합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
/// <summary>
/// 디바이스의 핸들을 가지고 온다.
/// https://docs.microsoft.com/ko-kr/windows/console/getstdhandle
/// </summary>
/// <param name="nStdHandle"></param>
/// <returns></returns>
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetStdHandle(int nStdHandle);
/// <summary>
/// 콘솔 모드를 가지고 온다.
/// https://docs.microsoft.com/ko-kr/windows/console/getconsolemode
/// </summary>
/// <param name="hConsoleHandle"></param>
/// <param name="lpMode"></param>
/// <returns></returns>
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
/// <summary>
/// 콘솔모드를 설정한다.
/// https://docs.microsoft.com/ko-kr/windows/console/setconsolemode
/// </summary>
/// <param name="hConsoleHandle"></param>
/// <param name="dwMode"></param>
/// <returns></returns>
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
|
cs |
'GetStdHandle'를 이용하여 수정할 콘솔의 핸들을 받아옵니다.
1
|
IntPtr consoleHandle = GetStdHandle(-10);
|
cs |
여기서 '-10'은 'STD_INPUT_HANDLE'을 의미합니다.
(참고 : MS Docs - GetStdHandle 함수 )
이렇게 받아온 핸들로 콘솔 모드를 가지고 옵니다.
1
2
3
4
|
//핸들에 설정된 콘솔 모드를 가지고 온다.
UInt32 consoleMode;
GetConsoleMode(consoleHandle, out consoleMode);
|
cs |
콘솔 모드를 설정하려면 아래와 같이 합니다.
1
2
3
4
5
6
|
//값을 넣을때
consoleMode |= ((uint)[모드 값]);
//값을 뺄때
consoleMode &= ~((uint)[모드 값]);
|
cs |
사용할 수 있는 모드값은 'MS Docs'를 참고하면 됩니다.
참고 - SetConsoleMode 함수
이제 값을 설정했으면 'SetConsoleMode'를 사용하여 수정한 설정값을 적용하면 됩니다.
1
2
|
//수정한 콘솔 모드를 설정한다.
SetConsoleMode(consoleHandle, consoleMode);
|
cs |
3. 테스트해보기
F11을 눌렀을 때 전체화면으로 전환되는 것을 막아 봅시다.
F11을 막기 위한 코드는 아래와 같습니다.
1
2
3
4
5
6
|
IntPtr consoleHandle = GetStdHandle((int)-10);
UInt32 consoleMode;
GetConsoleMode(consoleHandle, out consoleMode);
consoleMode &= ~((uint)0x0001);
SetConsoleMode(consoleHandle, consoleMode);
|
cs |
이제 전체화면 전환이 되지 않는 것을 알 수 있습니다.
'빠른 편집 모드'를 끄려면 '0x0040'를 입력하면 됩니다.
4. 캡슐화
인터넷을 돌아다니다가 이걸 쓰기 좋게 캡슐화된 게 있습니다.
참고 : stackoverflow 'Patrick from NDepend team' 님 답변 - How to programmatic disable C# Console Application's Quick Edit mode?
제가 살짝 정리를 한 건 이겁니다.
github - dang-gun/DotNetSamples/ConsoleModeSettingTest/
마무리
윈폼(Winform)처럼 자체적인 함수를 지원해주면 좋겠다는 생각을 하는데 말이죠.....
콘솔 응용프로그램이라는 게 UI없는 만큼 퍼포먼스가 좋으라고 쓰는 거라 그런 걸까요?