Language/C# WPF

[C#] FindWindow(), FindWindowEx()를 이용한 윈도우 창 찾기

멱군 2023. 9. 5. 17:46

누구나 프로그래밍 작업 중에 오류 메시지 창의 귀찮음을 경험해본 적이 있을 것입니다. 특히 윈도우 버전의 문제로 발생하는 오류 메시지는 사소하지만 사용자의 작업 효율을 방해합니다. 이 글에서는 C#에서 제공하는 FindWindow()와 FindWindowEx() 함수를 이용하여 자동으로 해당 오류 창을 찾아서 닫는 방법을 소개합니다.

 

 

1. 오류 창 자동 닫기의 필요성

프로그램 사용 중 발생하는 오류는 다양한 원인이 있을 수 있습니다. 윈도우 버전과의 호환성 문제, 잘못된 입력, 외부 리소스 문제 등 다양한 요인이 있습니다. 이런 오류 메시지는 사용자에게 중요한 정보를 제공하기도 하지만, 때로는 단순한 정보 전달을 위한 것일 수 있습니다. 이런 오류 메시지를 매번 수동으로 닫는 것은 사용자의 작업 효율을 방해하고, 사용자 경험을 저하시킵니다.

그래서 만약 어플리케이션 에러가 뜨면 자동으로 꺼주는 프로그램을 만들어보았습니다.

 

2. 문제의 해결 접근방법

1. SPY++로 윈도우 핸들 찾기

윈도우의 각 요소에는 고유한 핸들이 있습니다. 이 핸들을 통해 프로그래밍 언어로 윈도우 요소를 제어할 수 있습니다. SPY++는 윈도우 API를 이용하여 윈도우의 핸들 정보를 제공하는 도구입니다. 이 도구를 통해 오류 메시지 창의 핸들 정보를 쉽게 얻을 수 있습니다.

 

2. FindWindow(), FindWindowEx() 함수의 활용

FindWindow()는 주어진 윈도우의 이름을 기반으로 그 윈도우의 핸들을 반환하는 함수입니다. 반환된 핸들을 통해 윈도우를 제어할 수 있습니다. FindWindowEx()는 특정 윈도우의 하위 윈도우 핸들을 찾는 함수입니다. 이 두 함수를 조합하면, 원하는 오류 메시지 창의 핸들을 찾아 제어할 수 있습니다.

소스는 다음과 같이 추가합니다.

Using System.Runtime.InteropServices;

using 구문을 꼭 추가해주어야 합니다.

그리고 FindWindow(), FindWindowEx() 함수는 윈도우 APIs 함수들이므로,

[DllImport("user32.dll")]
public static extern int FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern int FindWindowEx(int hWnd1, int hWnd2, string lpsz1, string lpsz2);
[DllImport("user32")]
public static extern int SendMessage(int hwnd, int wMsg, int wParam, int lParam);
const int WM_LBUTTONDOWN = 0x0201;
const int WM_LBUTTONUP = 0x0202;
const int BM_CLICK = 0x00F5;

클래스 내부에 전역으로 선언을 해줍니다.

 

3. 클릭 이벤트 전송

윈도우의 핸들 정보를 얻었다면, SendMessage 함수를 이용하여 클릭 이벤트를 전송할 수 있습니다. 이를 통해 오류 메시지 창에 있는 "프로그램 닫기" 버튼을 자동으로 클릭하여 오류 창을 닫을 수 있습니다.

int nhwnd = FindWindow(null, "...MFC Application");    // 윈도우 창 제목
if (nhwnd > 0)
{
    int hw1 = FindWindowEx(nhwnd, 0, "DirectUIHWND", "");
    if (hw1 > 0)
    {
        int hw2 = FindWindowEx(hw1, 0, "CtrlNotifySink", "");
        if (hw2 > 0)
        {
            while (true)
            {
                int hw3 = FindWindowEx(hw2, 0, "Button", "프로그램 닫기");
                if (hw3 > 0)
                {
                    SendMessage(hw3, BM_CLICK, 0, 1);    //마우스 클릭이벤트
                    break;
                }
                hw2 = FindWindowEx(hw1, hw2, "CtrlNotifySink", "");
                if (hw2 == 0)
                {
                    break;
                }
            }
        }
    }
}

 

SPY++에서 보는 그림처럼 똑같은 클래스가 하위로 여러개 있는데 원하는 버튼이 들어있는 하위클래스를 찾기위해서는 hw1의 핸들 중 hw2의 핸들 다음번째 값을 넣어서 원하는 핸들 클래스로 넘어갑니다.

 hw2 = FindWindowEx(hw1, hw2, "CtrlNotifySink", "");

 

소스파일

위에서 사용한 코드의 소스파일을 압축하여 첨부합니다.

FindWindowex_Program.zip
0.00MB

 

결론

프로그래밍은 끊임없는 문제 해결 과정입니다. 오류 메시지 창은 때로는 중요한 정보를 제공하지만, 매번 수동으로 닫아야 하는 번거로움도 있습니다. C#의 FindWindow(), FindWindowEx() 함수를 활용하면, 이런 오류 메시지 창을 자동으로 찾아 닫는 프로그램을 만들 수 있습니다. 이를 통해 사용자의 작업 효율을 높이고, 더 나은 사용자 경험을 제공할 수 있습니다.

SPY++ 사용하는 방법 : [프로그래밍/etc] - spy++를 사용해서 사용클래스 및 핸들 알아보기

 

spy++를 사용해서 사용클래스 및 핸들 알아보기

복잡한 윈도우 프로그램 개발 중, 특정 프로그램의 동작, 클래스 구조 또는 핸들을 파악하고자 할 때 SPY++는 개발자에게 유용한 도구가 됩니다. 이번 글에서는 "MFC Application의 작동이 중지되었습

devit.koreacreatorfesta.com