标签: setwindowshookex

什么可以导致Windows取消挂钩低级(全局)键盘钩子?

我们必须通过安装一些全局键盘钩子SetWindowsHookExWH_KEYBOARD_LL看似随机获得由Windows脱钩.

我们验证了它们不再附加钩子,因为调用UnhookWindowsHookEx句柄返回false.(还验证了它true在正常工作时返回)

似乎没有一致的repro,我听说他们可以因为超时或异常被抛出而脱钩,但我已经尝试了两个只是让它在处理方法中断点超过一分钟,以及抛出一个随机异常(C#),它似乎仍然有效.

在我们的回调中,我们快速发布到另一个线程,这可能不是问题.我已经阅读了Windows 7中的解决方案,用于在注册表中设置更高的超时,因为Windows 7显然更加积极地执行超时(我们都在这里运行Win7,所以不确定这是否发生在其他操作系统上),但这并不是看起来似乎是一个理想的解决方案.

我考虑过只运行一个后台线程来每隔一段时间刷新一次钩子,这很黑,但我不知道这样做有什么真正的负面后果,而且它似乎比改变全局Windows注册表设置更好.

还有其他建议或解决方案? 设置挂钩的类和它们所附加的委托都是静态的,因此它们不应该是GC.

编辑:通过调用验证GC.Collect();他们仍然有效,因此他们没有被收集的垃圾.

c# keyboard-hook setwindowshookex

24
推荐指数
1
解决办法
8394
查看次数

SetWindowsHookEx失败,错误126

我正在尝试在项目中使用Gma.UserActivityMonitor库,我遇到了一个我自己无法克服的错误.

HookManager.Callbacks.cs文件中有一个静态方法EnsureSubscribedToGlobalMouseEvents,使用以下代码调用(或多或少):

var asm = Assembly.GetExecutingAssembly().GetModules()[0];
var mar = Marshal.GetHINSTANCE(asm);
s_MouseHookHandle = SetWindowsHookEx(
    WH_MOUSE_LL,
    s_MouseDelegate,
    mar,
    0);
//If SetWindowsHookEx fails.
if (s_MouseHookHandle == 0)
{
    //Returns the error code returned by the last unmanaged function called using platform invoke that has the DllImportAttribute.SetLastError flag set. 
    int errorCode = Marshal.GetLastWin32Error();
    //do cleanup

    //Initializes and throws a new instance of the Win32Exception class with the specified error. 
    throw new Win32Exception(errorCode);
}
Run Code Online (Sandbox Code Playgroud)

SetWindowsHookEx始终返回0和上面的代码中不断抛出与消息的异常 …

c# setwindowshookex

15
推荐指数
1
解决办法
7348
查看次数

在没有找到模块的32位机器上,.NET 4.0中的SetWindowsHookEx失败了吗?

我在这个页面上发现了类似的问题,但我似乎无法弄清楚如何解释答案或弄清楚它们是否真的重复.

以下是我发现的可能重复项,并附有评论:

Hans Passant对最后一个删除答案的评论如下:

你在使用.NET 4.0吗?它的CLR改变了程序集的加载方式,不再有LoadLibrary调用,也没有模块句柄.使用GetEntryAssembly()代替另一种修复. - 汉斯帕斯特5月5日19:43

那么,这里的字是什么?你在使用.NET 4.0吗?您是否尝试使用LoadLibrary("user32.dll")来获取可用的DLL句柄? - Hans Passant 5月6日15:43

我很确定我不需要这样做,但显然我不是百分百肯定.如果我需要更改它,我留下的问题是,为什么它适用于64位操作系统,在编译时Any CPU,但在任何配置中都不适用于32位.

如果加载.NET程序集确实发生了一些变化,那么我没有得到类库的正确句柄,我有以下问题:

  • 有没有什么方法可以欺骗我做我想要的,而不必降级到.NET 3.5或将钩子库更改为不受管理?
  • 为什么它在64位操作系统上运行时有效,而在32位运行时无效?

背景

我在.NET 4.0中构建了一个程序,它使用带有WH_KEYBOARD_LL钩子类型的SetWindowsHookEx来捕获按键.这在我的64位Windows 7上运行良好,但在32位Windows 7上安装键盘挂钩时崩溃时出现"找不到模块".

这是我尝试过的:

  • 编译为x86,在64位操作系统上运行,崩溃时出现"找不到模块"
  • 编译x86,在32位操作系统上运行,崩溃
  • 编译任何CPU,在64位操作系统上运行,运行良好
  • 编译任何CPU,在32位操作系统上运行,崩溃
  • 切换到.NET 3.5并重复上述四种情况,它们都有效

我宁愿不将我的代码切换到.NET 3.5,因为我使用了一些类库来简化工作,而最新的代码只在.NET 4.0中.

如果需要,可以下载包含Visual Studio 2010项目的.ZIP文件,也可以粘贴以下两个文件.

要重新创建是否要沿着该路线前进:

  1. 创建一个新的控制台项目.NET 4.0
  2. 添加另一个类库项目,也就是.NET 4.0
  3. 从控制台程序项目添加对类库项目的引用
  4. 将下面的Program.cs内容粘贴到控制台项目中的Program.cs文件中
  5. 将下面的Hook.cs内容粘贴到类库项目中的文件中.您可以将其粘贴到Class1.cs默认文件中,或添加另一个文件.你不能把它放到控制台项目中

然后构建并运行,测试各种配置.

Program.cs中

using System;
using HookLib;

namespace HookTest
{
    class Program
    {
        static void Main() …
Run Code Online (Sandbox Code Playgroud)

64-bit 32-bit .net-4.0 .net-3.5 setwindowshookex

14
推荐指数
1
解决办法
5092
查看次数

是否可以删除应用程序收到的触摸消息(WM_POINTERDOWN等)?

我已经成功地安装一个WH_GETMESSAGE带有钩SetWindowsHookEx,我可以看到的WM_POINTERDOWN,WM_POINTERUP等应用程序接收消息.(它是在Windows 8.1上运行的32位桌面应用程序.)

现在,我不仅希望看到这些消息,而且还想删除其中一些消息.

GetMsgProc的文档说:

GetMsgProc挂钩过程可以检查或修改消息.在钩子过程将控制权返回给系统之后,GetMessage或PeekMessage函数将消息以及任何修改返回给最初调用它的应用程序.

有了WM_KEYUP消息,这似乎工作正常.我可以将消息设置为WM_NULL挂钩,并且键事件将消失.

WM_POINTER...但是,对于消息,这似乎不起作用.应用程序仍然接收消息(在调试器中验证).

也许有其他方法来过滤/删除此类消息?

编辑:它必须使用未修改的第三方应用程序(因此使用钩子).

更新:我设法通过积极调用PeekMessage钩子来阻止点击事件(从长远来看可能不是一个好主意).但是,我仍然无法阻止通过触摸滚动.

c++ winapi touch setwindowshookex windows-8

11
推荐指数
1
解决办法
2454
查看次数

C#中的SetWindowsHookEx

我正试图挂钩第三方应用程序,以便我可以绘制到它的屏幕.在屏幕上绘图是容易的,我需要它没有帮助,但我似乎有使用问题SetWindowsHookEx来处理WH_GETMESSAGE.我无法弄清楚最后两个参数传递的内容.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowDrawer
{
    public partial class Form1 : Form
    {
        private delegate int HookProc(int code, IntPtr wParam, IntPtr lParam);
        static IntPtr hHook;
        IntPtr windowHandle;
        uint processHandle;

        HookProc PaintHookProcedure;     

        [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
        static extern System.IntPtr FindWindowByCaption(int ZeroOnly, string lpWindowName);

        [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SetWindowsHookEx", SetLastError = true)]
        static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint …
Run Code Online (Sandbox Code Playgroud)

c# setwindowshookex wm-paint

10
推荐指数
2
解决办法
4万
查看次数

如何使用LowLevelKeyboardHook挂钩Win + Tab

在几句话:堵Win起来后Win+ Tab使Windows认为Win仍下降,所以然后按SWin键向上例如会打开搜索的魅力,而不是在用户按下只需键入"S" ...... Win一次.阻止它意味着Windows开始菜单将显示.我陷入了一个难题!


我可以使用Alt+ Tabusing LowLevelKeyboardHookWin+ Some Ubounded Keyusing 挂钩快捷方式RegisterHotKey.只有使用Win密钥才会出现问题LowLevelKeyboardHook.

在下面的示例中,我在检测到+ 组合Win时接管up事件.这导致使每个后续击键行为都像键仍然关闭一样.WinTabWin

        private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode != HC_ACTION)
                return CallNextHookEx(_hookID, nCode, wParam, lParam);

            var keyInfo = (Kbdllhookstruct)Marshal.PtrToStructure(lParam, typeof(Kbdllhookstruct));

            if (keyInfo.VkCode == VK_LWIN)
            {
                if (wParam == (IntPtr)WM_KEYDOWN) {
                    _isWinDown …
Run Code Online (Sandbox Code Playgroud)

c# windows keyboard-shortcuts keyboard-hook setwindowshookex

10
推荐指数
1
解决办法
809
查看次数

SetWindowsHookEx创建一个本地钩子.如何使其全球化?

在Delphi XE应用程序中,我正在尝试设置一个全局挂钩来监视焦点更改.钩子是在一个DLL中创建的:

focusHook := SetWindowsHookEx( WH_CBT, @FocusHookProc, HInstance, 0 );
// dwThreadId (the last argument) set to 0 should create a global hook
Run Code Online (Sandbox Code Playgroud)

在同一个DLL中,我有一个将消息发布到主机应用程序窗口的钩子过程:

function FocusHookProc( code : integer; wParam: WPARAM; lParam: LPARAM ) : LResult; stdcall;
begin
  if ( code < 0 ) then
  begin
    result := CallNextHookEx( focusHook, code, wParam, lParam );
    exit;
  end;

  result := 0;

  if ( code = HCBT_SETFOCUS ) then
  begin
    if ( hostHWND <> INVALID_HANDLE_VALUE ) then
      PostMessage( hostHWND, cFOCUSMSGID, wParam, lParam ); …
Run Code Online (Sandbox Code Playgroud)

delphi hook winapi setwindowshookex

9
推荐指数
1
解决办法
7142
查看次数

WH_JOURNALRECORD的SetWindowsHookEx在Vista/Windows 7下失败

我正在准备一个Delphi模块,它在一个线程中设置一个钩子来记录一个宏:

FHandleRec  := SetWindowsHookEx(WH_JOURNALRECORD, FRecordProc, HInstance, 0);
FHandlePlay := SetWindowsHookEx(WH_JOURNALPLAYBACK, FPlayProc, HInstance, 0);
Run Code Online (Sandbox Code Playgroud)

这在WinXP上工作正常,但在Vista/Windows 7上失败了ERROR_ACCESS_DENIED.我在谷歌(这个)中找到了(那个).报价单:

较低权限进程不能:...使用Journal钩子来监视更高权限的进程.

尝试没有成功:

  1. 以管理员身份运行应用 可能线程以比主线程更低的权限启动(虽然我不是100%肯定)
  2. 使用管理员安全上下文模拟线程也无济于事.

代码示例:

if LogonUser(PWideChar(sAdminUser), PWideChar(sDomain), PWideChar(sPwd),
             LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, hToken) then 
begin  
  if not ImpersonateLoggedOnUser(hToken) then
    raise Exception.Create('Error impersonating the user');
end;
FHandleRec := SetWindowsHookEx(WH_JOURNALRECORD, FRecordProc, HInstance, 0);
Run Code Online (Sandbox Code Playgroud)

LogonUserImpersonateLoggedOnUser执行没有错误.

尝试的其他可能性:

  1. 永久关闭UAC.这有帮助,但我不能强迫模块用户这样做.
  2. 模块客户签署应用程序并将其放在受信任的位置.没有尝试过,但这极大地使用户的模块使用复杂化.
  3. 将模块放入一些已签名的应用程序并分发EXE.这将打破一些核心功能.

您能否在Visa/Windows 7下显示设置挂钩的代码或建议工作解决方案?

delphi winapi windows-vista windows-7 setwindowshookex

8
推荐指数
1
解决办法
2844
查看次数

键盘钩子用delphi寻找F12

这个问题可能已经得到解答,但我一直无法找到正确的答案.我正试图在表单中按下F12键时切换调试开关.我无法使用onkeydown事件,因为我必须为每个字段设置一个单独的函数以及表单.所以我研究并发现了SetWindowsHookEx函数来设置键盘钩子.这个工作得很好,除了我得到两个指示F12键每次按下时都按下:

2014/05/21 14:16:43.334
Code: 0
Key: 123
KeyStroke: 5767169
KeyStroke to Hex: 00580001
2014/05/21 14:16:43.446
Code: 0
Key: 123
KeyStroke: -1067974655
KeyStroke to Hex: C0580001  Note: this should be the keystroke that reflects KEYDOWN
Run Code Online (Sandbox Code Playgroud)

我看到Keystroke是检查keydown的可能方法(WM_KEYDOWN $ 0100).我的问题是如何为WM_KEYDOWN测试击键?

这是我的回调函数:

function KeyboardHookProc(Code: Integer; Key: Word; KeyStroke: LongInt) : LongInt;
begin
  Result := 0;
  if Code = HC_NOREMOVE then exit;
  Result := CallNextHookEx(FkbHook, Code,Key,KeyStroke);
  if Code < 0  then exit;

{
WM_KEYDOWN

}
  if (KeyStroke and WM_KEYDOWN) = 0 then { this is …
Run Code Online (Sandbox Code Playgroud)

delphi setwindowshookex

8
推荐指数
1
解决办法
999
查看次数

如何将参数传递给 SetWindowsHookEx 的回调?(如果可能的话)

我使用 SetWindowsHookEx 和 WH_CALLWNDPROC 来捕获所有 WndProc 消息 - 它工作正常。我想知道是否有一种方法可以将参数存储在回调函数可以读取和使用的地方。

我假设因为回调函数位于“其他”进程内部,所以与调用 SetWindowsHookEx 的进程没有连接,因此仅将值存储在静态变量中不会有任何好处。

例如:

void Hook(DWORD dwThread, int randomNumber)
{
    MagicallyStore(randomNumber);
    SetWindowsHookEx(WH_CALLWNDPROC, hookProc, GetModuleHandle(L"WNDProcHooks"), dwThread);
    ...
    ...
}

LRESULT CALLBACK hookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    int randomNumber = MagicallyRestore();

    DoSomthing(randomNumber);

    return CallNextHookEx(0, nCode, wParam, lParam);
}
Run Code Online (Sandbox Code Playgroud)

我已经考虑过让“MagicallyStore”函数将参数写入文件并在“MagicallyRestore”函数中读取一次 - 但必须有更好的方法..

提前致谢 :)

hook winapi c++-cli setwindowshookex

8
推荐指数
0
解决办法
1643
查看次数