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