Windows (C++) 中的 WH_JOURNALRECORD 挂钩 - 从未调用过回调。

Posted

技术标签:

【中文标题】Windows (C++) 中的 WH_JOURNALRECORD 挂钩 - 从未调用过回调。【英文标题】:WH_JOURNALRECORD hook in Windows (C++) - Callback never called. 【发布时间】:2010-07-01 11:14:08 【问题描述】:

在过去的几个小时里,以下代码一直给我带来一些麻烦。 我正在尝试编写一个小程序(基于网络上的一些教程),它使用 WH_JOURNALRECORD 窗口挂钩来记录击键。

主要代码:

#include "StdAfx.h"
#include <tchar.h>
#include <iostream>
#include <windows.h>

using std::cout;
using std::endl;

int _tmain(int argc, _TCHAR* argv[])   
    HINSTANCE hinst = LoadLibrary(_T("testdll3.dll")); 
    typedef void (*Install)();
    typedef void (*Uninstall)();
    Install install = (Install) GetProcAddress(hinst, "install");
    Uninstall uninstall = (Uninstall) GetProcAddress(hinst, "uninstall");

    install();
    int foo;
    std::cin >> foo; 

    cout << "Uninstalling" << endl;
    uninstall();
    return 0;

DLL 代码:

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

HHOOK hhk;
HHOOK hhk2;


LRESULT CALLBACK journalRecordProc(int code, WPARAM wParam, LPARAM lParam)   
    FILE * fileLog = fopen("journal.txt", "a+");
    fprintf(fileLog,"loggedJournal\n");
    fclose(fileLog);
    CallNextHookEx(hhk,code,wParam,lParam);
    return 0;



LRESULT CALLBACK wireKeyboardProc(int code,WPARAM wParam,LPARAM lParam)   
 FILE * fileLog = fopen("keyboard.txt", "a+");
 fprintf(fileLog,"loggedKeyboard\n");  
 fclose(fileLog);
 CallNextHookEx(hhk,code,wParam,lParam);
 return 0;


extern "C" __declspec(dllexport) void install() 
    HINSTANCE thisDllInstance = LoadLibrary(_T("testdll3.dll"));
    hhk = SetWindowsHookEx(WH_JOURNALRECORD, journalRecordProc, thisDllInstance, NULL);
    hhk2 = SetWindowsHookEx(WH_KEYBOARD, wireKeyboardProc, thisDllInstance, NULL);

extern "C" __declspec(dllexport) void uninstall() 
    UnhookWindowsHookEx(hhk); 
    UnhookWindowsHookEx(hhk2); 


BOOL WINAPI DllMain(  __in  HINSTANCE hinstDLL, __in  DWORD fdwReason, __in  LPVOID lpvReserved) 
 return TRUE;

由于某种原因,键盘挂钩 (SetWindowsHookEx(WH_KEYBOARD, wireKeyboardProc,..)) 有效(创建了 'keyboard.txt' 文件),但日志挂钩 (SetWindowsHookEx(WH_JOURNALRECORD, journalRecordProc,...))没有。也就是说,日志挂钩的回调永远不会被调用(journal.txt 文件永远不会被创建)。

我认为这可能与 Windows 的 UAC(我在搜索网络时发现)有关,但禁用 UAC 并以管理权限运行程序并没有帮助。

我不知道现在该做什么。谁能帮帮我?

谢谢

乔里斯

附加信息:我使用的是 Windows 7 + Visual Studio 2010

编辑: 原来这确实和访问权限有关。也就是说,从 Windows Vista 开始,出于安全原因,日志挂钩 (WH_JOURNALRECORD) 被禁用(另请参阅 this website)。最后,我们使用了一种完全不同的方法在我们的应用程序中提供类似的功能(我不会在这里详细介绍,因为我在问这个问题 1.5 年后正在编辑这个问题,我不记得所有的我们解决方案的详细信息)。

【问题讨论】:

【参考方案1】:

WH_JOURNALRECORD 不同于其他。您不需要将其放入 DLL,但您确实需要在您的应用程序中有一个消息循环,以便可以调用处理程序(在您的应用程序的上下文中)。我前段时间在另一个站点上发布了一个示例:http://forum.4programmers.net/viewtopic.php?p=557297#id557297,钩子在示例中捕获 WM_MOUSEMOVE 并将结果打印到控制台。

这种钩子很昂贵,因为每次调用回调时都必须将执行上下文切换到您的应用程序。

【讨论】:

【参考方案2】:

答案,根据已编辑问题中的链接:

http://www.wintellect.com/CS/blogs/jrobbins/archive/2008/08/30/so-you-want-to-set-a-windows-journal-recording-hook-on-vista-it-s-not-nearly-as-easy-as-you-think.aspx

    应用程序需要以管理权限运行。 应用程序必须c:\program files(的子目录)运行 要禁用 UAC 对话框,必须对应用进行数字签名。 请注意,使用 UAC 活动的 Windows(Vista 及更高版本)将不允许调试 exe。

或者...您可以禁用 UAC(在调试时很有用)。

这是 Visual Studio 的设置对话框,将检查是否可以获取 XML 格式的清单文件

【讨论】:

【参考方案3】:

MSDN 为日志记录挂钩声明以下内容:

与大多数其他全局挂钩不同 程序,JournalRecordProc 和 JournalPlaybackProc 挂钩程序 总是在上下文中调用 设置钩子的线程。

如果您将 Journal 挂钩的回调移动到您的 exe,这会导致它被调用吗?

另外,由于 DLL 已经加载,在 install() 中调用 GetModuleHandle() 而不是 LoadLibrary() 不是更好吗?

关于 UAC 和管理员权限,挂钩可以在以普通用户身份执行时工作。唯一的副作用是只有在该级别或更低级别运行的进程才会被挂钩。因此,如果您的应用程序以普通用户身份运行,那么任何以普通用户身份运行的进程都会被挂钩,但以管理员身份运行的进程不会被挂钩。

【讨论】:

嗯,我不完全确定您的意思是“如果您将 Journal 挂钩的回调移动到您的 exe,这会导致它被调用吗?”我尝试不从 exe 中调用 SetWindowsHookEx 和 UnhookWindowsHookEx(显然,我也将回调复制到了 exe),但是这样做时没有调用回调(甚至没有 WH_KEYBOARD 回调......)。我还尝试将回调作为函数指针从 exe 传递到 dll,但这不起作用(运行时错误)。还有其他想法吗?谢谢 我的意思是 SetWindowsHookEx() 和回调过程都应该在你的 exe 中定义,而不是在 dll 中。这是因为此回调是在您的应用程序中调用的,而不是在发送消息的应用程序中。

以上是关于Windows (C++) 中的 WH_JOURNALRECORD 挂钩 - 从未调用过回调。的主要内容,如果未能解决你的问题,请参考以下文章

如何访问 C++ windows 10 应用程序中的默认线程池?

“Windows 无法访问指定的设备.....” C++ 中的错误

在 Windows 上使用 C++ 中的 system(),为啥调用另一个目录中的程序需要两个引号?

Windows 中的线程有啥好的初学者教程吗? C++ [关闭]

c++ 中是不是有类似 java 中的 Desktop 类的类? (特定于 Windows)

Borland C++ Builder 中的 Windows 子类化