Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi中使用VCL的Shell名称空间扩展_Delphi_Com_Vcl - Fatal编程技术网

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

Delphi中使用VCL的Shell名称空间扩展,delphi,com,vcl,Delphi,Com,Vcl,Shell名称空间扩展相当复杂。在过去10年中,我们一直在构建一个shell名称空间扩展;最新版本是MagicRAR(www.MagicRAR.com)中的归档文件夹功能 不幸的是,我们的shell名称空间扩展仍然偶尔会出现崩溃,尽管编码非常仔细,确保线程正确地访问共享内存等等。Explorer主机进程在使用shell命名空间扩展期间或之外崩溃 我们已经使用了各种工具,如AQTime Pro来解决shell名称空间扩展代码的故障。没有报告内存覆盖或其他类似的访问问题。这只剩下一个罪魁祸首:VCL

Shell名称空间扩展相当复杂。在过去10年中,我们一直在构建一个shell名称空间扩展;最新版本是MagicRAR(www.MagicRAR.com)中的归档文件夹功能

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

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

事实上,我们正在使用VCL作为shell名称空间扩展的一部分;资源管理器中的文件列表实际上是一个托管控件,对于我们自己的shell名称空间扩展,它实际上是一个VCL窗口。我们现在甚至想知道(经过几代人的开发)这是否是一个允许的场景

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

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

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

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

ShellPlus实际上还提供了使用Explorer自己的预定义主机窗口的功能,而不是创建自定义VCL窗口;虽然这可能会避开任何VCL线程问题,但根据我们的经验,即使这样也不是一个可行的解决方案,因为ShellPlus shell命名空间扩展始终不如我们自己编写的代码稳定,无论是否使用VCL窗口

所以首先,;这个问题是一个理论问题——VCL是否可以用于将资源管理器中的VCL窗口用作进程主机的shell命名空间扩展


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

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

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



您可以通过确保在被告知时有人检查队列来解决同步挂起问题,但如果没有“主”线程,则不清楚您将与什么进行同步,因此
同步
可能不是该作业的正确工具。

我们终于能够解决此问题。 即将发布的MagicRAR 9.0将以固定shell名称空间扩展为特色。 问题确实出在VCL上——否则我们的代码就完美无缺了。 对于尝试使用Delphi构建shell命名空间扩展的任何其他人:

是的,您可以使用Delphi构建shell名称空间扩展。 但是-如果您使用VCL,您将经历无数随机崩溃和不稳定。 如果您没有使用VCL,那么使用Delphi没有什么意义。
好消息是您不需要修补VCL源。只需使用专用的VCL线程。

您是否确实检查了与GUI相关的代码是否在每个进程中以多个线程运行?Win32有自己的线程规则。特别是windows具有线程关联性。我希望任何时候资源管理器希望您使用窗口句柄,您总是会在同一线程中被调用。换言之,我怀疑线程关联性是否实际上是您的问题。如果资源管理器对线程关联性很小心,这很好,但是当多个资源管理器窗口中显示了VCL窗口的多个副本时会发生什么情况?VCL不是线程安全的,因此仍然存在多个线程在同一进程内执行GUI工作的问题,而不是单个线程处理所有GUI工作。事实上,Explorer创建了多个线程来调用shell名称空间扩展。好吧,在这一点上,您就被套住了。那么这是否意味着Delphi总体上不适合构建shell名称空间扩展,至少就GUI而言是这样?一点也不。如果你可以用C++做,你可以用Delphi来做。但是VCL听起来似乎不是一个选项。我想知道尝试创建一个“主”VCL线程是否有意义,它将拥有所有GUI工作,处理所有同步,并成为所有同步的目标()请注意,如果VCL不能用于管理shell命名空间扩展的GUI部分,那么它就无法实现在项目中使用Delphi的目的。如果这根本不可能做到,那么重建项目可能更有意义