2016-09-14 4 views
3

다양한 메시지 (예 : WM_POINTERMOVE, WM_KEYDOWN 등)를 보내서 다시 컴파일하지 않고 제어해야하는 미리 컴파일 된 WPF 응용 프로그램이 있습니다. 내가 시도한 제어 방법은 메시지를 애플리케이션 메시지 펌프에 주입하는 것이었다. 테스트로 나는 다른 Win32 응용 프로그램에서이 응용 프로그램에 대한 Windows 핸들을 얻은 다음 SendMessage 메시지를 보내도록 시도했습니다. WPF 응용 프로그램 메시지 펌프에 메시지 주입

BOOL CALLBACK EnumWindowsProc(
_In_ HWND hwnd, 
_In_ LPARAM lParam 
) 
{ 
    LPWSTR windowName = new TCHAR[256]; 
    GetWindowText(hwnd, windowName, 256); 
    std::wstring windowNameString(windowName); 
    int position = windowNameString.find(std::wstring(L"MyApplicationWindowName")); 
    if (position > -1) { 
     hTargetWindow = hwnd; 
     delete windowName; 
     return FALSE;//stop enumerating windows 
    } 
    delete windowName; 
    return TRUE; 
} 

..... 
EnumWindows(EnumWindowsProc, NULL);; 
SendMessage(hTargetWindow, MY_MESSAGE, 0, 0); 

내가 (잘 작동) EnumWindows를 사용하여 응용 프로그램의 HWND를 검색. 그런 다음 SendMessagePostMessage을 사용하여 메시지를 보냅니다. 다른 응용 프로그램은이 WPF 응용 프로그램에 응답하지 않지만. 다른 테스트로 WPF 애플리케이션을 만들고 코드를 추가하여 특정 메시지를 받았을 때 중단 점을 설정할 수있었습니다.

ComponentDispatcher.ThreadFilterMessage += (ref MSG msg, ref bool handled) => 
{ 
    if(msg.message == MY_MESSAGE) 
     Debug.WriteLine("break"); 
}; 

메시지가 메시지 펌프로 전달되고 있지 않음을 나타내는 중단 점은 절대로 표시되지 않습니다. 다른 유형의 응용 프로그램에서 동일한 것을 시도하면 성공할 수 있습니다. 이 메시지를 주입하는 것이 잘못된 것입니다.

+0

필자는 모르지만 메모리 누수가 발생했습니다. 'LPWSTR windowName = new TCHAR [256];' –

+1

[UI Automation] (https : // msdn.microsoft.com/en-us/library/windows/desktop/ee684009.aspx)는 아마도 우리가 알지 못하는 것보다 더 나은 해결책 일 것입니다. – IInspectable

+0

다음은 현재 수행중인 작업을 요약 한 것입니다. 일부 응용 프로그램의 비디오 출력을 캡처하는 응용 프로그램 (모든 응용 프로그램이 동일한 컴퓨터에서 실행되는 것은 아님)이 함께 혼합되어 있습니다. 창이 캡처되면 마우스 및 터치 메시지를 더 이상 수신 할 수 없습니다. WPF 애플리케이션으로 메시지를 라우팅하기 위해 이들 모두를 관리하는 애플리케이션을 원했습니다. 이미 WPF가 아닌 Windows가 캡처 된 Win32 앱에서이 작업이 이미 진행 중입니다. – Joel

답변

1

여기에 더 자세한 응답을 보내고 싶지만 시간이 부족합니다. 요약을 여기에 올리겠습니다. 나는 똑같은 일을하기를 원하는 몇몇 다른 사람들을 찾았다.

Windows 메시지를 처리하는 WPF 클래스는 추가 검사를 수행합니다. 마우스 메시지의 정보를 처리하는 대신 마우스 메시지를 받으면 WPF는 마우스 커서를 쿼리하여 실제 위치를 확인하고 실제로 포커스가 있는지 확인합니다 (이와 유사한 검사는 일부 다른 입력 메시지에 대해 완료). 이러한 검사 중 하나라도 WPF 클래스 라이브러리의 주석에 따라 실패하면 WPF에서 실수로 메시지를 가져 오는 일부 조건이 발생했다고 가정합니다. WPF 응용 프로그램이 포커스를 갖도록하여 시나리오에 맞게 작업 할 수있었습니다.

또한 WP32 동작 중 일부를 재정의하기 위해 프록시 User32.dll을 만드는 등의 작업을 수행하지 말아야 할 몇 가지 작업을 수행해야했습니다. 이것은 제 목적을 위해 작동했지만 단일 운영 체제 버전에서만 작동합니다. 다행히도 필자의 목표 컴퓨터는 인터넷에 연결되지 않으며 1 년 정도 작업을 수행해야하며 격리 된 환경에서 OS 업데이트를받지 못합니다. Windows Update는이 솔루션을 쉽게 죽일 수 있습니다.

1

불행히도 Windows 메시지를 수신하려면 WPF 응용 프로그램에서 메서드를 명시 적으로 재정의해야합니다 (here 참조).

HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle); 
source.AddHook(new HwndSourceHook(WndProc)); 

분명히 소스를 다시 컴파일하지 않으면이 작업을 수행 할 수 없으므로 다른 방법이 필요합니다.


편집

나는 이전에 당신의 선택의 어떤 코드에 원래의 방법 핸들러에서 리디렉션을 주입하는 EasyHook을 제안했다. 주석이 올바로 언급되었으므로 원래 응용 프로그램이 Windows 메시지를받지 못하기 때문에 문제가 해결되지 않습니다. UI 자동화를 사용하기위한 제안을 환영합니다.

+0

보내는 메시지는 WM_KEYDOWN과 같은 메시지입니다. WPF 응용 프로그램이 이미 일반 키 및 마우스 메서드로 처리 할 수 ​​있다고 생각합니다. 나는 지금 무슨 일이 일어나고 있는지 알 수 있도록 메시지 펌프 핸들러를 오버라이드 한 테스트 애플리케이션에 대해 이것을 시도하고있다. Windows 메시지를 처리하고 있지만 보내지는 메시지가 아닌 것입니다. EasyHook을 살펴 봅니다. – Joel

+1

예 EasyHook를 확인하십시오. 상태 대화 상자를 생성 한 호출을 스텁으로 리디렉션하여 FORTRAN 응용 프로그램을 강제로 '자동 모드'로 만들었습니다. 치료를 했어. – Steztric

+3

@Joel : * ""WM_KEYDOWN과 같은 메시지를 보낼 예정입니다. "* - [PostMessage로 키보드 입력을 시뮬레이션 할 수 없습니다] (https://blogs.msdn.microsoft.com/oldnewthing/20050530-11/? p = 35513 /). UI 자동화를 사용하십시오. EasyHook도 도움이되지 않습니다. 들어오는 메시지를 필터링하려고하지 않습니다. 가짜 입력을 시도하고 있습니다. – IInspectable

관련 문제