2009-06-25 103 views
6

我正忙于编写一个为主机应用程序提供多种功能的DLL。 该应用程序动态调用dll,在每次函数调用后加载并释放它。德尔福动态Dll - 全局变量

我无法控制主机应用程序。我只能在dll内工作。 有没有办法让内存中的某些变量保留下来,以便我可以在每个函数中重用它们?很明显,当主机应用程序卸载dll时,全局可变数据就会被清除。 保存DLL文件听起来非常混乱!

任何人都可以提出一种方法来分配一个变量,我可以保持全球?

谢谢

+3

您的设计很糟糕,原因很多。你有没有想过多个主机应用程序(快速用户切换,在终端服务器下使用)或主机应用程序从多个线程调用DLL函数的可能性?不惜一切代价尽量避免全局/共享状态。 – mghie 2009-06-25 09:45:47

回答

4

我认为你在这里有两个主要选项。

  1. 报价2版本的功能,你现在有一个,加上另一个地方,他们在缓冲区(记录,等等),你可以读取以前的状态,当然更新状态为通过。称这是函数的高性能版本。他们会想要使用它。

  2. 保存喜欢你的状态会一个cookie(那基本上它是什么)在文件中的某个地方。

选项1将需要修改主机应用程序,但将是引人注目的主机应用程序开发人员采取的,选项2优点将不需要改变到主机应用程序,但不会像高性能的。

我不会亲自倾向于开始摆弄引用计数,想必主机应用程序正在卸载是有原因的,如果我是主机应用开发,这将激怒了我。

+0

谢谢 - 我认为这是最好的选择。 我宁愿保存到文件并采取性能比风险而不是摆弄dll引用。也许主机应用程序开发人员将继续提供高性能版本 – Crudler 2009-06-26 12:30:27

1

最好的方法是使用包含“全局变量”的类。您实例化一个对象并将其作为参数提供给dll函数。但这不会帮助你,因为你无法更改调用应用程序。

如果你必须保持全局数据在DLL中,一个解决方案是将它们写入文件。但这对性能造成严重影响。

0

如果我是你,我会的全局变量的值保存到一个文件时,该dll被释放,当它被初始化加载它们。我没有理由保存磁盘上的DLL的内存转储。

4

警告,肮脏的黑客:

您可以加载自己。

每次调用LoadLibrary递增引用计数器,FreeLibrary递减它。只有当计数器达到零时,DLL才会被卸载。

因此,如果第一次你的DLL被加载时,你又把您的书架,从而增加引用计数器。如果调用应用程序调用FreeLibrary引用计数器递减,但该DLL不会被卸载。

编辑:正如mghi指出,如果进程终止,DLL是否会被卸载,引用计数是否为零。

+1

是的,但是这个方法再次增加了很多关于何时决定dll应该真正卸载的时间,因为它不需要一直运行。该dll然后应该检查主机应用是否仍然存在定期,我不太喜欢,但这只是我。 – zz1433 2009-06-25 09:17:43

+3

@Aldo:不正确 - 如果只有一个进程使用该DLL,那么一旦该进程退出,引用计数是否已达到0,它将被卸载。 – mghie 2009-06-25 09:30:01

2

如果你有大量的全局数据要共享,另一个解决方案是创建一个windows服务来“缓存”状态数据。您还需要实现某种跨越进程边界的IPC,例如内存映射文件,邮箱,COM(本例为单实例),TCP/IP等。您可能会发现这种开销不仅仅是将状态写入文件,这就是为什么我只会在状态数据量过多时才推荐这种方法,或者只会在每个请求的整个部分处理这些数据进入你的dll。

对于COM方法,除了请求(并保持)将用于维护状态的com对象的实例之外,服务不必做太多的事情。由于它是一个单实例com对象,因此所有请求都将发送给同一个实例,从而允许您在请求之间保存状态。对该对象的请求将被序列化,因此,如果您有多个客户端同时在同一台计算机上请求数据,则这可能是性能问题。

0

当DLL被释放时将值写入注册表,并且在加载DLL时从注册表读取值。当读取发现没有设置密钥时,不要忘记提供默认值。

-Al。

0

我同意之前关于全球状态信息危险的评论,尽管我可以想象它可能是需要的。

我提出DR的肮脏的黑客更清洁的版本不具有作为永久像skamradt的回答的缺点:

一个非常小的应用程序:

它没有外观无论如何,它让自己从显示在任务栏上。

任务#1:加载DLL

任务#2:把它的命令行,运行它,并等待它终止。

任务#3:卸载DLL

任务#4:退出。

安装程序:

它找到快捷方式(多个)到主应用程序,并修改它们所以小应用程序运行时,原始位置的快捷指向变成第一参数。

结果:只有主应用程序正在运行,DLL才会保留在内存中,但每次程序转储时它都不会被卸载。

0

这也可能是有益的

option 1: 创建握着你的页面文件支持的变量共享内存区 - 如果你能打开共享内存区,你的DLL以前加载(假设“私人“共享内存名称,可能名称与process_id_yourdllname类似) - 如果您无法打开它,那么您首次创建并初始化它。如果你创建了它,那么你不用去删除它 - 但是如果你打开它,你会在卸载时关闭它。我相信当应用程序关闭时该区域将被释放,因为没有其他应用程序应该处理这个特定的“私有”共享内存区域。

option 2: 创建第二个。只存在用于管理全局变量的dll。你的DLL A可以加载该DLL B,而不是释放它,放入DLL B无论你需要管理全局变量。当应用程序消失时它应该消失,我认为你可能不需要关心(可能是无用的)引用计数(因为你不会卸载dll B)。