Delphi中使用VCL的Shell命名空间扩展



Shell名称空间扩展非常复杂。在过去的10年里,我们一直在构建shell命名空间扩展;它的最新化身是MagicRAR中的存档文件夹功能(www.magicrar.com)。

不幸的是,尽管非常仔细地编写代码,确保线程正确访问共享内存等,但shell名称空间扩展仍然偶尔会崩溃。资源管理器主机进程在使用shell命名空间扩展期间或之外崩溃。

我们已经使用了各种工具,如AQTime Pro来解决shell名称空间扩展代码的故障。没有内存覆盖或其他类似的访问问题报告。这就只剩下一个问题了:VCL不是线程安全的!

实际上,我们正在使用VCL作为shell命名空间扩展的一部分;Explorer中的文件列表实际上是一个托管控件,在我们自己的shell命名空间扩展的情况下,它实际上是一个VCL窗口。我们现在甚至想知道(经过几代人的开发)这是否首先是一个允许的场景…

主应用程序对象甚至不存在于shell命名空间扩展DLL中。使用TThread。同步死锁资源管理器,因为没有在任何地方创建主VCL线程。我们是否需要手动创建一个主VCL线程(如何?)-可能在另一个DLL内-并通过该DLL重新路由我们所有的UI创建/更新/销毁?

请记住,资源管理器可以显示任意数量的包含VCL窗口的窗口。根据目标系统的配置,Explorer也可以作为多个独立进程运行,或者作为单个进程运行。

我们的shell命名空间扩展基于John Lam的出发点(大多数Delphi shell命名空间开发人员都知道)。当然,正如您在最终产品中看到的那样,对这个起点进行了大量修改。John Lam从未在他的幻灯片和示例项目中讨论过VCL线程不安全的问题。

在过去的十年中,我们也尝试使用多个版本的ShellPlus组件。他们做了一些出色的工作,但不幸的是,根据我们的经验,即使是基于他们代码的非常基本的努力也会提供比我们自己的代码更差的结果。

ShellPlus实际上还提供了使用资源管理器自己预定义的主机窗口的能力,而不是创建一个自定义的VCL窗口;虽然这可能会避免任何VCL线程问题,但根据我们的经验,即使这也不是一个可行的解决方案——因为ShellPlus shell命名空间扩展总是比我们自己编写的代码更不稳定,无论VCL是否有窗口。

所以首先;这个问题是一个理论问题- VCL可以在shell命名空间扩展中使用,该扩展使用资源管理器中的VCL窗口作为进程主机?

如果是这样,在这种情况下如何处理VCL线程不安全的问题?

VCL确实不是线程安全的。在VCL应用程序之外运行并不能摆脱这一规则。缺少主VCL线程只会使情况变得更糟;VCL控件期望在主线程的上下文中运行,通常没有这样的线程,也不可能有这样的线程。你所使用的控件在没有任何同步保护的情况下访问各种全局变量,如果你不能修补任何VCL控件使用的所有单元,你就无能为力了。

使用常规的Windows API技术,而不是VCL函数,在资源管理器中创建和操作窗口。


您可以通过确保在被告知时检查队列来解决同步挂起问题,但如果没有"主"线程,则不清楚您将如何将同步,因此Synchronize可能不是适合这项工作的工具。

我们终于能够解决这个问题了。固定的shell名称空间扩展将在即将发布的MagicRAR 9.0中出现。问题确实出在VCL上——我们的代码在其他方面完全没问题。对于任何试图用Delphi构建shell命名空间扩展的人:

是的,你可以用Delphi构建shell命名空间扩展。但是-如果你使用VCL,你会遇到无数的随机崩溃和不稳定。如果您不使用VCL,那么使用Delphi就没有什么意义了。好消息是您不需要修补VCL源代码。

最新更新