Windows 7 64bit,已经成功安装了全角键盘钩子,来捕获所有的键盘消息,在我的程序中使用CreateProcess()创建了一个子进程,然后通过EnumThreadWindow() 获得了子进程中是WS_VISIBLE属性的窗口句柄(主窗口),然后使用SetForegroundWindow()将子进程设置到TOP LEVEL顶层窗口,到这一步都是成功的。再使用SendInput()函数发送一组合键:Ctrl+T,结果就会返回“拒绝访问”。
使用Process Explorer查看我的程序和子进程,他们都有相同的等级medium,所以我的键盘钩子能够在任何窗口(包括我创建的子进程)发送消息到我的程序,然后我的程序根据用户的按键再往子进程发送键盘消息。但是使用SendInput()函数总是返回“拒绝访问”。
我认为是UIPI的问题。
如何解决这个问题呢?
谢谢!
>>我认为是UIPI的问题。
SendInput()函数如果如果返回0,表明输入操作被另一个线程阻断了,我们可以使用GetLastError函数来获取错误信息。这个函数失败了则是由于UIPI引起的,这在GetLastError或返回值中是反映不出来的,就像您说的这个问题很可能是由于UIPI引起。
UIPI介绍:
在早期的Windows操作系统中,在同一用户下运行的所有进程有着相同的安全等级,拥有相同的权限。从Windows Vista开始,当然也包括Windows 7,对于某些Windows消息,这一方式再也行不通了。进程(或者其他的对象)开始拥有一个新的属性——特权等级(Privilege Level)。一个特权等级较低的进程不再可以向一个特权等级较高的进程发送消息,虽然他们在相同的用户权限下运行。这就是所谓的用户界面特权隔离 (User Interface Privilege Isolation,UIPI)。
解决方案:
调用ChangeWindowMessageFilterEx,该函数修改指定窗口的UIPI消息过滤设置。原型如下:
BOOL WINAPI ChangeWindowMessageFilterEx( HWND hWnd, UINT message, DWORD action, PCHANGEFILTERSTRUCT pChangeFilterStruct);第一个参数要改变设置的窗口句构, 第二个参数要过滤的消息, 第三个参数要执行的动作, 第四个参数指向一个CHANGEFILTERESTRUCT结构。该结构用于返回修改结果。 另外ChangeWindowMessageFilterEx在需要从user32中导出, 如下:BOOL CallChangeWindowMessageFilter(HWND hWnd, UINT nMsg, DWORD dwAction, PCHANGEFILTERSTRUCT chfit){ typedef BOOL (WINAPI *LPFUNC)(HWND, UINT, DWORD, PCHANGEFILTERSTRUCT); HMODULE hLib = LoadLibraryA("user32.dll"); if (hLib) { LPFUNC func = (LPFUNC)GetProcAddress(hLib, "ChangeWindowMessageFilterEx"); if (func && chfit) return func(hWnd, nMsg, dwAction, chfit); } return FALSE;}
CHANGEFILTERSTRUCT chfit = { sizeof(CHANGEFILTERSTRUCT) };
CallChangeWindowMessageFilter(hWnd, WM_COPYDATA, MSGFLT_ALLOW, &chfit);
g_hhookCBTMsg = SetWindowsHookExW(WH_CBT ,CBTProc, hDLL, 0);
如果您的问题解决了,请把有用的回答标记为答案。
谢谢,
Lucy
Hi jigsong,
请尝试用管理员权限登录Visual Studio。
在Visual Studio的图标上,按右键,选Run as an administrator。
如果您的问题解决了,请把有用的回答标记为答案。
谢谢,
Lucy
你好!
操作系统:Windows 7家庭高级版64位,
VS2005,
操作系统登录帐户类型:管理员(但用户名不是Administrator,是自己定义的。这和旗舰版的管理员帐户名是Administrator不同)。
我试了以管理员权限(右击选择)打开VS2005,并重新生成了解决方案,然后执行“Ctrl+F5”执行程序,但是仍得到“拒绝访问”的结果。直接打开生成的程序(右击选择管理员权限)同样结果"拒绝访问“.
非常感谢lucy-liu(google中文输入法中“lucyliu”有惊喜)!
经过排查程序,在我程序逻辑上出了点小问题造成上述子进程不能正常执行SendInput()发来的按键消息的,现在已经能够正常执行。但仍有异常。
为了程序需要我不会把任何按键放行,现在把“Ctrl+T”放行后即可正常执行,但程序仍有异常,那就是我的子进程程序都已经接受"Ctrl+T"并执行了该项功能,但是主进程对于使用SendInput()函数仍获得“拒绝访问”的提示。这个现在很不解?!
联系客服