公司程序有被夺取焦点的情况,需要用户手动切出切入,暂写个demo(其实是挖坑)

查找焦点丢失的问题

查百度说是有其他程序抢夺了焦点,有人写了小程序,我也搜一下,模仿模仿.
在模仿过程中,不幸用了个系统推荐但不熟悉函数(wcscpy_s():为了这个专门加了个miniDump,可不知道为什么还是定位不到),挖了个坑,在此主要就是为了记录这个坑.

定时器是个很不好的方法,不过指示测试的话也够了.
为什么别人家的代码看起来那么好用,我就只配用定时器,没天理啊!!!

原参考:如何找到WIN7中夺去焦点的程序? - 知乎 @liyb

// 代码备份
// 定时器检查获取前端窗口
// 2020-1-7 17:56:39
// GetFocusInfo.cpp
#include <iostream>
#include <Windows.h>
#include "DbgHelp.h"

#define DUMPMSGBOX

// windows下c++代码保存dump文件_jigetage的专栏-CSDN博客
// https://blog.csdn.net/jigetage/article/details/80757559
int GenerateMiniDump(PEXCEPTION_POINTERS pExceptionPointers)
{
    
    
	MessageBox(NULL, L"Init", L"GenerateMiniDump", MB_OK);
	// 定义函数指针
	typedef BOOL(WINAPI * MiniDumpWriteDumpT)(
		HANDLE,
		DWORD,
		HANDLE,
		MINIDUMP_TYPE,
		PMINIDUMP_EXCEPTION_INFORMATION,
		PMINIDUMP_USER_STREAM_INFORMATION,
		PMINIDUMP_CALLBACK_INFORMATION
		);
	// 从 "DbgHelp.dll" 库中获取 "MiniDumpWriteDump" 函数
	MiniDumpWriteDumpT pfnMiniDumpWriteDump = NULL;
	HMODULE hDbgHelp = LoadLibrary(TEXT("DbgHelp.dll"));
	DUMPMSGBOX MessageBox(NULL, L"DbgHelp.dll", L"LoadLibrary", MB_OK);
	if (NULL == hDbgHelp)
	{
    
    
		return EXCEPTION_CONTINUE_EXECUTION;
	}
	pfnMiniDumpWriteDump = (MiniDumpWriteDumpT)GetProcAddress(hDbgHelp, "MiniDumpWriteDump");

	if (NULL == pfnMiniDumpWriteDump)
	{
    
    
		FreeLibrary(hDbgHelp);
		return EXCEPTION_CONTINUE_EXECUTION;
	}
	DUMPMSGBOX MessageBox(NULL, L"MiniDumpWriteDump", L"GetProcAddress", MB_OK);
	// 创建 dmp 文件件
	TCHAR szFileName[MAX_PATH] = {
    
     0 };
	TCHAR* szVersion = TEXT("DumpDemo_v1.0");
	SYSTEMTIME stLocalTime;
	GetLocalTime(&stLocalTime);
	wsprintf(szFileName, L"%s-%04d%02d%02d-%02d%02d%02d.dmp",
		szVersion, stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
		stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond);
	HANDLE hDumpFile = CreateFile(szFileName, GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_WRITE | FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
	if (INVALID_HANDLE_VALUE == hDumpFile)
	{
    
    
		FreeLibrary(hDbgHelp);
		return EXCEPTION_CONTINUE_EXECUTION;
	}
	DUMPMSGBOX MessageBox(NULL, L"szFileName", L"CreateFile", MB_OK);
	// 写入 dmp 文件
	MINIDUMP_EXCEPTION_INFORMATION expParam;
	expParam.ThreadId = GetCurrentThreadId();
	expParam.ExceptionPointers = pExceptionPointers;
	expParam.ClientPointers = FALSE;
	pfnMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
		hDumpFile, MiniDumpWithDataSegs, (pExceptionPointers ? &expParam : NULL), NULL, NULL);
	// 释放文件
	CloseHandle(hDumpFile);
	FreeLibrary(hDbgHelp);
	DUMPMSGBOX MessageBox(NULL, L"hDbgHelp", L"FreeLibrary", MB_OK);
	return EXCEPTION_EXECUTE_HANDLER;
}
LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS lpExceptionInfo)
{
    
    
	DUMPMSGBOX MessageBox(NULL, L"Init", L"ExceptionFilter", MB_OK);
	// 这里做一些异常的过滤或提示
 	if (IsDebuggerPresent())
 	{
    
    
 		return EXCEPTION_CONTINUE_SEARCH;
 	}
	return GenerateMiniDump(lpExceptionInfo);
}


// SetUnhandledExceptionFilter无法捕获异常原因及解决方法_kevin3683的专栏-CSDN博客
// https://blog.csdn.net/kevin3683/article/details/19040809
void DisableSetUnhandledExceptionFilter()
{
    
    

// 无法得知此代码来源于
#ifndef _M_IX86
#error "The following code only works for x86!"
#endif
// 此函数一旦成功调用,之后对 SetUnhandledExceptionFilter 的调用将无效

	void* addr = (void*)GetProcAddress(LoadLibrary(L"kernel32.dll"), "SetUnhandledExceptionFilter");

	if (addr)
	{
    
    
		unsigned char code[16];
		int size = 0;

		code[size++] = 0x33;
		code[size++] = 0xC0;
		code[size++] = 0xC2;
		code[size++] = 0x04;
		code[size++] = 0x00;

		DWORD dwOldFlag, dwTempFlag;
		VirtualProtect(addr, size, PAGE_READWRITE, &dwOldFlag);
		WriteProcessMemory(GetCurrentProcess(), addr, code, size, NULL);
		VirtualProtect(addr, size, dwOldFlag, &dwTempFlag);
	}
}


int main()
{
    
    
	SetUnhandledExceptionFilter(ExceptionFilter);
	DisableSetUnhandledExceptionFilter();  // 不加这个,会有些Crash捕获不到,比如wcscpy_s()

	// 基于VS2010 开发的Release版本软件异常崩溃后快速定位bug相关方法_tormi21c的博客-CSDN博客
	// https://blog.csdn.net/tormi21c/article/details/88376619
// 	int *c = NULL;
// 	*c = 123;

	// wchar_t 的输出问题_风吹草地pp凉的博客-CSDN博客
	// https://blog.csdn.net/blue1244/article/details/9245029
	// 设置输出编码
	std::wcout.imbue(std::locale("chs"));
	std::wcout.imbue(std::locale(""));
	setlocale(LC_ALL, "Chinese-simplified");

	int iBufLen = 1024;
 	WCHAR*strWnd = new WCHAR[iBufLen];
 	memset(strWnd, 0, iBufLen);
 	WCHAR*strCtrl = new WCHAR[iBufLen];
 	memset(strCtrl, 0, iBufLen);
	while (true)
	{
    
    
		// 获取活动窗口输入焦点控件句柄的方法_leevans的专栏-CSDN博客
		// https://blog.csdn.net/leevans/article/details/7318023
		// 获取活动窗口及获得控件句柄
		HWND hForeWnd = ::GetForegroundWindow();
		DWORD dwSelfThreadId = GetCurrentThreadId();
		DWORD dwForeThreadId = GetWindowThreadProcessId(hForeWnd, NULL);
		AttachThreadInput(dwForeThreadId, dwSelfThreadId, true);

		HWND hFocus = ::GetFocus();
		GetWindowTextW(hForeWnd, strWnd, iBufLen-1);
		if (hFocus != NULL)
		{
    
    
			GetWindowTextW(hFocus, strCtrl, iBufLen-1);
		}
		else
		{
    
    
			WCHAR wc[128] = L"[NULL]";
			wcscpy(strCtrl, wc);
			//wcscpy_s(strCtrl, wcslen(wc), wc);  // Release异常退出,Debug未抓取到,miniDump定位不到
		}

		DWORD pid = 0;
		DWORD dRtn = GetWindowThreadProcessId(hForeWnd, &pid);
		AttachThreadInput(dwForeThreadId, dwSelfThreadId, false);

		// 输出内容
		printf("\n==========%lld\n", GetTickCount64());
		printf("当前进程ID      :%u\n", GetCurrentProcessId());     
		printf("当前线程ID      :%u\n", dwSelfThreadId);            
		printf("活动进程ID      :%u\n", pid);
		printf("活动线程ID      :%u\n", dwForeThreadId);

		printf("活动窗口句柄    :%d(10) - %x(16)\n", hForeWnd, hForeWnd);
		printf("活动控件句柄    :%d(10) - %x(16)\n", hFocus, hFocus);
		printf("活动窗口标题[%d]:%ws\n", wcslen(strWnd), strWnd); 
		printf("活动控件标题[%d]:%ws\n", wcslen(strCtrl), strCtrl);

		Sleep(3000);
	}
	delete[] strWnd;
	delete[] strCtrl;

	return 0;
}

猜你喜欢

转载自blog.csdn.net/u012101384/article/details/103879418