我正在创建一个自我更新的应用程序,其中我将大部分代码放在一个单独的DLL中。这是命令行,最终将在Mono上运行。我只是试图让这段代码在命令行的Windows上使用C#。
如何创建一个c#应用程序,我可以在运行时删除支持的dll?
AppDomain domain = AppDomain.CreateDomain("MyDomain");
ObjectHandle instance = domain.CreateInstance( "VersionUpdater.Core", "VersionUpdater.Core.VersionInfo");
object unwrap = instance.Unwrap();
Console.WriteLine(((ICommand)unwrap).Run());
AppDomain.Unload(domain);
Console.ReadLine();
在ReadLine中,VersionUpdater.Core.dll仍然被锁定而无法删除
ICommand接口位于VersionUpdater.Common.dll中,该命令行应用程序和VersionUpdater.Core.dll都引用了
答案 0 :(得分:6)
我曾经管理类似的东西的唯一方法是将DLL放在一个单独的AppDomain中,然后尝试删除它。我卸载其他AppDomain,然后从磁盘中删除DLL。
如果您正在寻找一种方法来执行更新,那么我会选择一个存根exe来生成真正的AppDomain。然后,当该存根exe检测到要应用更新时,它将退出其他AppDomain,然后执行更新魔术。
编辑:更新程序无法与正在更新的事物共享DLL,否则它将锁定这些DLL,从而阻止它们被删除。我怀疑这就是你仍然得到例外的原因。更新程序必须是独立的,不依赖于其他AppDomain使用的任何内容,反之亦然。
答案 1 :(得分:1)
Unwrap会将对象类型的程序集加载到调用它的appdomain中。解决此问题的一种方法是在“基础”程序集中创建一个调用command.run的类型,然后将其加载到新的appdomain中。这样,您就不必从另一个程序集中的类型调用对象的解包,并且可以删除磁盘上的程序集。
答案 2 :(得分:1)
当我构建一个自我更新的应用程序时,我使用了存根的想法,但存根是应用程序本身。
应用程序将启动,查找更新。如果发现更新,它会将新应用程序的副本下载到临时存储,然后使用命令行选项启动它(System.Diagnostics.Process.Start()),该选项表示“您正在更新”。然后原来的exe退出。
生成的exe启动,发现它是一个更新,并将自身复制到原始的app目录。然后它从该新位置启动应用程序。然后产生的exe结束。
原始应用安装位置新启动的exe启动 - 查看临时文件并删除它。然后恢复正常执行。
答案 3 :(得分:1)
您可以随时使用MOVEFILE_DELAY_UNTIL_REBOOT
在重新启动时删除。这很可能是最简单的hackey方式,通过hackey,我通常会看到类似的东西;加载新的DLL或注入explorer.exe甚至修补系统dll以加载到另一个进程等...
MoveFileEx From MSDN;
lpNewFileName [in, optional ]新的 上的文件或目录的名称 本地电脑。
当移动文件时,目的地 可以在不同的文件系统或 体积。如果目的地已开启 另一个驱动器,你必须设置 dwFlags中的
MOVEFILE_COPY_ALLOWED
标志。移动目录时, 目的地必须在同一个驱动器上。
如果dwFlags指定
MOVEFILE_DELAY_UNTIL_REBOOT
和 lpNewFileName是 NULL , MoveFileEx 注册lpExistingFileName文件 系统时删除 重新启动。如果lpExistingFileName引用 到一个目录,系统删除 只有在重启时才能重启目录 目录是空的。