【发布时间】:2011-10-14 23:10:06
【问题描述】:
我正在尝试将程序中的 Windows 挂钩设置为外部 EXE。这将用于监视窗口的大小调整/最小化,因此我可以类似地调整程序大小,停靠到窗口。
如何绕过以下错误代码 1428 和 126?
当使用 null hMod 调用 SetWindowsHookEx 时,我收到此错误 1428。如果传递当前模块(而不是 IntPtr.Zero),我会得到同样的错误,它似乎是正确的,如下所示:
IntPtr module = PInvoke.GetModuleHandle(null);
[...]
SetWindowsHookEx(...,...,module,...);
int error = PInvoke.GetLastError();
1428 = 不能在没有模块句柄的情况下设置非本地挂钩
我还尝试使用 GetModuleHandle 来获取我作为模块连接的外部程序:
IntPtr module = PInvoke.GetModuleHandle("communicator.exe");
int error = PInvoke.GetLastError();
但是 error 然后设置为:
126 = 找不到指定的模块。
我正在使用以下 PInvoke 语句:
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(HookType hookType, HookProc lpfn, IntPtr hMod, uint dwThreadId);
这是有问题的程序:
public void Install(IntPtr hWnd)
{
uint threadId;
uint processId;
if (hWnd == IntPtr.Zero)
{
threadId = (uint)AppDomain.GetCurrentThreadId();
throw new Exception("Lync thread not found!");
}
else
{
threadId = PInvoke.GetWindowThreadProcessId(hWnd, out processId);
}
//IntPtr module = PInvoke.GetModuleHandle(null);
//IntPtr module = PInvoke.GetModuleHandle(GetType().Module.FullyQualifiedName);
IntPtr module = PInvoke.GetModuleHandle("communicator.exe");
int error = PInvoke.GetLastError();
m_hhook = PInvoke.SetWindowsHookEx(
m_hookType,
m_filterFunc,
//Process.GetCurrentProcess().Handle,
//threadId);
//IntPtr.Zero,
//module,
//Marshal.GetHINSTANCE(
// System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0]
// ).ToInt32()
module,
threadId);
//IntPtr hinst = Marshal.GetHINSTANCE(Process.GetCurrentProcess().Handle);
// http://msdn.microsoft.com/en-us/library/ms681385
// ERROR_HOOK_NEEDS_HMOD - 1428 = Cannot set nonlocal hook without a module handle
error = PInvoke.GetLastError();
}
【问题讨论】:
-
您遗漏了重要的部分,但错误代码足够清晰,您无法使用 C# 代码设置全局挂钩。
-
有什么替代方案?我是否必须编写一个外部 C++ DLL 来处理它?
-
另外我认为向 SetWindowsHookEx 提供一个线程 ID 使它成为一个线程钩子——而不是一个全局钩子——所以我认为它是被允许的。
-
模块句柄必须是加载到您的进程中的 DLL 的句柄。该 DLL 必须包含过滤函数(非托管函数)。然后 Windows 会将该 DLL 加载到系统中的每个进程中,并根据需要在每个进程中调用过滤器函数。所以是的,它需要在 C/C++ DLL 中才能工作。
-
"Windows 会将该 DLL 加载到系统中的每个进程中,并根据需要在每个进程中调用过滤器函数。"哦,好吧,有道理,很好的解释
标签: c# hook pinvoke setwindowshookex