应用程序X继续执行
例如CBT钩子(window创建等等)的钩子类型并不切换上下文对于这些类型的钩子过程大致如下
应用程序X拥有焦点并执行
应用程序X创建一个窗口
Windows用在应用程序X进程空间中的CBT事件消息参数调用钩子回调函数
应用程序X继续执行
这应该说明了为什么某种类型的钩子能够用这个库结构工作而一些却不能记住这正是该库要做的在上面第步和第步之后分别插入下列步骤
Windows调用钩子回调函数
目标回调函数在非托管的DLL中执行
目标回调函数查找它的相应托管的调用代理
托管代理被以适当的参数执行
目标回调函数返回并执行相应于指定消息的钩子处理
第三步和第四步因非切换钩子类型而注定失败第三步将失败因为相应的托管回调函数不会为该应用程序而设置记住这个DLL使用全局变量来跟蹤这些托管代理并且该钩子DLL被加载到每一个进程空间但是这个值仅在放钩子的应用程序进程空间中设置对于另外其它情况它们全部为null
Tim Sylvester在他的《Other hook types》一文中指出使用一个共享内存区段将会解决这个问题这是真实的但是也如Tim所指出的那些托管代理地址对于除了放钩子的应用程序之外的任何进程是无意义的这意味着它们是无意义的并且不能在回调函数的执行过程中调用那样会有麻烦的
因此为了把这些回调函数使用于不执行上下文切换的钩子类型你需要某种进程间的通讯
我已经试验过这种思想使用非托管的DLL钩子回调函数中的进程外COM对象进行IPC如果你能使这种方法工作我将很高兴了解到这点至于我的尝试结果并不理想基本原因是很难针对各种进程和它们的线程(CoInitialize(NULL))而正确地初始化COM单元这是一个在你可以使用COM对象之前的基本要求
我不怀疑一定有办法来解决这个问题但是我还没有试用过它们因为我认为它们仅有有限的用处例如CBT钩子可以让你取消一个窗口创建如果你希望的话可以想像为使这能够工作将会发生什么
钩子回调函数开始执行
调用非托管的钩子DLL中的相应的钩子回调函数
执行必须被路由回到主钩子应用程序
该应用程序必须决定是否允许这一创建
调用必须被路由回仍旧在运行中的钩子回调函数
在非托管的钩子DLL中的钩子回调函数从主钩子应用程序接收到要采取的行动
在非托管的钩子DLL中的钩子回调函数针对CBT钩子调用采取适当的行动
完成钩子回调函数的执行
这不是不可能的但是不算好的我希望这会消除在该库中的围绕被允许的和受限制的钩子类型所带来的神秘
七其它
◆库文档我们已经包含了有关ManagedHooks类库的比较完整的代码文档当以Documentation构建配置进行编译时这被经由Visual StudioNET转换成标准帮助XML最后我们已使用NDoc来把它转换成编译的HTML帮助(CHM)你可以看这个帮助文件只需简单地在该方案的解决方案资源管理器中点击Hookschm文件或通过查找与该文相关的可下载的ZIP文件
◆增强的智能感知如果你不熟悉Visual StudioNET怎样使用编译的XML文件(preNDoc output)来为参考库的工程增强智能感知那么让我简单地介绍一下如果你决定在你的应用程序中使用这个类库你可以考虑复制该库的一个稳定构建版本到你想参考它的位置同时还要把XML文档文(SystemHooks\ManagedHooks\bin\Debug\KennedyManagedHooksxml)复制到相同的位置当你添加一个参考到该库时Visual StudioNET将自动地读该文件并使用它来添加智能感知文档这是很有用的特别是对于象这样的第三方库
◆单元测试我相信所有的库都应有与之相应的单元测试既然我是一家公司(主要负责针对NET环境软件的单元测试)的合伙人和软件工程师任何人不会对此感到惊讶因而你将会在名为ManagedHooksTests的解决方案中找到一个单元测试工程为了运行该单元测试你需要下载和安装HarnessIt这个下载是我们的商业单元测试软件的一个自由的试用版本在该单元测试中我对这给予了特殊的注意在此处方法的无效参数可能导致C++内存异常的发生尽管这个库是相当简单的但该单元测试确实能够帮助我在一些更为微妙的情况下发现一些错误
◆非托管的/托管的调试有关混合解决方案(例如本文的托管的和非托管的代码)最为技巧的地方之一是调试问题如果你想单步调试该C++代码或在C++代码中设置断点你必须启动非托管的调试这是一个Visual StudioNET中的工程设置注意你可以非常顺利地单步调试托管的和非托管的层但是在调试过程中非托管的调试确实严重地减慢应用程序的装载时间和执行速度
八最后警告
很明显系统钩子相当有力量然而使用这种力量应该是有责任性的在系统钩子出了问题时它们不仅仅垮掉你的应用程序它们可以垮掉在你的当前系统中运行的每个应用程序但是到这种程度的可能性一般是很小的尽管如此在使用系统钩子时你还是需要再三检查你的代码
我发现了一项可以用来开发应用程序的有用的技术它使用系统钩子来在微软的虚拟PC上安装你的喜爱的开发操作系统的一个拷贝和Visual StudioNET然后你就可以在此虚拟的环境中开发你的应用程序用这种方式当你的钩子应用程序出现错误时它们将仅退出你的操作系统的虚拟实例而不是你的真正的操作系统我已经不得不重启动我的真正的OS在这个虚拟OS由于一个钩子错误崩溃时但是这并不经常
注意如果你在网上订阅了一个MSDN那么在你整个订阅过程中你可以自由使用虚拟PC
[] [] [] [] []