我们正在使用包装器DLL以允许自动更新我们的应用程序(我们的产品是DLL)。
当应用程序关闭时,我们应该在哪里释放内部DLL?
(我们尝试在DLLMain回调中执行此操作,但它似乎不起作用,并且规范说它不应该在那里。)
谢谢
答案 0 :(得分:2)
这很模糊,根本不清楚你的包装器是做什么的。通常,将DLL加载到进程中会锁定文件。此锁被创建为Windows将DLL映射到进程的虚拟内存地址空间的副作用,底层系统对象是内存映射文件。这会在更新文件时尝试覆盖文件失败。
在“应用程序关闭时”的情况下,您不必执行任何特殊操作,这样也可以卸载DLL并释放文件锁。
更典型的问题是,您无法控制加载DLL的进程。在该过程终止之前,您的更新无法完成。很明显,DLL永远不应该强行终止主机进程,它无法判断将要发生什么样的损害。 可能的包装器方法是为每个导出函数提供入口点的方法,该函数将调用委托给真实的DLL。使用GetProcAddress()找到了谁的入口点,现在可以使用FreeLibrary()来卸载真正的DLL,以便更新它。当DLL不是很简单时,这是非常痛苦和容易出错的,你需要为每个导出的函数提供一个函数指针声明,并使用字符串而不是函数名。维护非常残酷。
一种可能的替代方法是DLL上的锁定在DLL的文件数据上,而不是在目录条目上。这允许您在加载文件时重命名文件。您的更新现在可以使用相同的名称编写更新的版本。程序下次启动时,它将使用您的更新。然而,这并不完全可靠,显然程序将无法启动,就像您应用更新一样。考虑使用hard-link来避免失败模式。
答案 1 :(得分:1)
我假设您在检查(并可能应用)内部DLL的可用更新后,使用LoadLibrary()从包装DLL动态加载内部DLL。
如果您使用包装器DLL与主机进程合作,则可以导出应该在退出之前由主机调用的Uninitialize()方法。在这个例程中,您可以调用FreeLibrary()并进行任何其他清理。
如果您没有主持人流程的合作,那么您通常不能正确清理。正如您所发现的那样,不允许在DllMain中调用FreeLibrary(),这是DLL正常关闭进程的唯一通知。
在进程关闭期间泄漏DLL模块句柄实际上不是一个大问题;系统正在跟踪所有资源并自动清理它们。