gpt4 book ai didi

.net-3.5 - SetWindowsHookEx 在 32 位机器上的 .NET 4.0 中失败,代码为 "module not found"?

转载 作者:行者123 更新时间:2023-12-03 21:41:35 24 4
gpt4 key购买 nike

我在此页面上发现了类似的问题,但我似乎无法弄清楚如何解释答案或弄清楚它们是否真的重复。
以下是我发现的可能重复项,并附有评论:

  • SetWindowsHookEx returns 0 when compiling for the .NET 4.0 framework in 32bit machines
    我的似乎没有返回 0,但我注意到当它崩溃时报告的句柄(32 位上的 .NET 4.0)与它运行时报告的句柄(32 位上的 .NET 3.5)有很大不同,比如崩溃句柄 = 523727,工作句柄 = 172738378。
  • Calling SetWindowsHookEx inside VS2008 debugger always returns NULL
    在 Visual Studio 之外运行时,我可以重现我的问题
  • Module not found
    这似乎最有希望,除了对已删除答案的评论提到我应该使用 LoadLibrary 和 GetProcAddress 在 .NET 4.0 中加载 user32.dll,因为有关加载程序集的某些内容发生了变化。但是,我很确定这是我自己的模块,它找不到,但我不知道这是否适用。

  • 汉斯·帕桑特(Hans Passant)对已删除的最后一个答案的评论如下:

    Are you using .NET 4.0? Its CLR changed the way assemblies are loaded, there is no longer a LoadLibrary call, there won't be module handle for them. Using GetEntryAssembly() instead would be another fix. – Hans Passant May 5 at 19:43

    So, what's the word here? Are you using .NET 4.0? Did you try using LoadLibrary("user32.dll") to get a usable DLL handle? – Hans Passant May 6 at 15:43


    我很确定我不需要这样做,但显然我不是 100% 确定。如果我需要更改它,我留下的问题是为什么它在为 Any CPU 编译时可以在 64 位操作系统上工作。 ,但在任何配置中都不适用于 32 位。
    如果在加载 .NET 程序集方面确实发生了一些变化,以至于我无法正确处理类库,那么我有以下问题:
  • 有什么办法可以欺骗它做我想做的事,而不必降级到 .NET 3.5 或将钩子(Hook)库更改为非托管?
  • 为什么在 64 位操作系统上运行时它可以工作,但在 32 位操作系统上却不行?

  • 背景
    我在 .NET 4.0 中构建了一个程序,它使用带有 WH_KEYBOARD_LL 钩子(Hook)类型的 SetWindowsHookEx 来捕获按键。这在我的 64 位 Windows 7 上运行良好,但在 32 位 Windows 7 上安装键盘 Hook 时会因“找不到模块”而崩溃。
    这是我尝试过的:
  • 为 x86 编译,在 64 位操作系统上运行,因“找不到模块”而崩溃
  • 为 x86 编译,在 32 位操作系统上运行,崩溃
  • 为任何 CPU 编译,在 64 位操作系统上运行,运行良好
  • 为任何 CPU 编译,在 32 位操作系统上运行,崩溃
  • 切换到.NET 3.5,重复以上四种情况,都行

  • 我宁愿不将我的代码切换到 .NET 3.5,因为我正在使用我的一些类库来简化工作,而最新的代码仅在 .NET 4.0 中。
    您可以 download a .ZIP-file with everything as a Visual Studio 2010 project如果需要,也可以粘贴以下两个文件。
    如果你想沿着这条路线重新创建:
  • 创建一个新的控制台项目,.NET 4.0
  • 添加另一个类库项目,也是 .NET 4.0
  • 从控制台程序项目中添加对类库项目的引用
  • 将下面的 Program.cs 内容粘贴到您在控制台项目中的 Program.cs 文件中
  • 将下面的 Hook.cs 内容粘贴到类库项目中的文件中。您可以将其粘贴到 Class1.cs 默认文件中,或添加另一个文件。你 不能将此放入控制台项目

  • 然后编译运行,测试各种配置。
    程序.cs
    using System;
    using HookLib;

    namespace HookTest
    {
    class Program
    {
    static void Main()
    {
    var hook = new Hook();

    Console.Out.WriteLine("hooking");
    hook.Enable();
    Console.Out.WriteLine("hooked");

    Console.Out.WriteLine("unhooking");
    hook.Disable();
    Console.Out.WriteLine("unhooked");
    }
    }
    }
    钩子(Hook).cs
    using System;
    using System.ComponentModel;
    using System.Reflection;
    using System.Runtime.InteropServices;

    namespace HookLib
    {
    public class Hook
    {
    private IntPtr _Handle;
    private HookProcDelegate _Hook;

    public void Enable()
    {
    Module module = Assembly.GetExecutingAssembly().GetModules()[0];
    if (module != null)
    Console.Out.WriteLine("found module");
    IntPtr moduleHandle = Marshal.GetHINSTANCE(module);
    if (moduleHandle != IntPtr.Zero)
    Console.Out.WriteLine("got module handle: " +
    moduleHandle.ToString());
    _Hook = HookProc;
    _Handle = SetWindowsHookEx(WH_KEYBOARD_LL, _Hook, moduleHandle, 0);
    if (_Handle == IntPtr.Zero)
    throw new Win32Exception(Marshal.GetLastWin32Error());
    }

    public void Disable()
    {
    bool ok = UnhookWindowsHookEx(_Handle);
    _Handle = IntPtr.Zero;
    if (!ok)
    throw new Win32Exception(Marshal.GetLastWin32Error());
    }

    private delegate int HookProcDelegate(
    int code, IntPtr wParam, IntPtr lParam);

    private int HookProc(int code, IntPtr wParam, IntPtr lParam)
    {
    return CallNextHookEx(_Handle, code, wParam, lParam);
    }

    private const int WH_KEYBOARD_LL = 13;

    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr SetWindowsHookEx(
    int hookType, HookProcDelegate lpfn, IntPtr hMod, uint dwThreadId);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern bool UnhookWindowsHookEx(IntPtr hhk);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern int CallNextHookEx(
    IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
    }
    }

    最佳答案

    是的,我想你明白发生了什么。 SetWindowsHookEx() 需要一个有效的模块句柄,并对其进行验证,但当您设置低级 Hook 时,它实际上并没有使用它。您只需要一个有效的句柄,哪个特定的句柄都没有关系。调用 LoadLibrary("user32.dll") 是获取句柄的好方法,因为您 P/Invoke 它的方法,DLL 将始终被加载。它总是由 CLR Bootstrap (mscoree.dll) 加载。不要打扰调用 FreeLibrary(),它没有区别。

    更高版本的 Windows 不再执行此检查。不完全确定什么时候开始的,我想是在 Windows 7 SP1 附近的某个地方。可能意味着有帮助,但会调用“在我的机器上工作,而不是客户的”失败场景。

    关于.net-3.5 - SetWindowsHookEx 在 32 位机器上的 .NET 4.0 中失败,代码为 "module not found"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3671673/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com