【问题标题】:Executing and then Deleting a DLL in c#在 C# 中执行然后删除 DLL
【发布时间】:2009-05-29 14:48:41
【问题描述】:

我正在创建一个自我更新的应用程序,其中大部分代码都在一个单独的 DLL 中。它是命令行,最终将在 Mono 上运行。我只是想让这段代码在命令行的 Windows 上的 C# 中工作。

如何创建一个可以在运行时删除支持 dll 的 c# 应用程序?

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 都引用了该接口

【问题讨论】:

  • 你为什么要把它做成一个wiki?你应该接受代表。这是个好问题。
  • 哦,拍摄不知道我没有得到代表
  • 您肯定已经在这里回答了自己的问题。如果您是更新者并且您正在更新共享代码,那么两个 AppDomains 都会锁定该代码,因此您无法删除它。更新者不能尝试更新自己的代码,那是行不通的。
  • 我想我要在命令行应用程序上编写启动和停止调用,这样我就可以等待线程完成而不是终止进程来更新它。
  • 使用 MEF 或 Mono Addins 可能会有解决方案

标签: mono appdomain self-updating


【解决方案1】:

我曾经管理过类似事情的唯一方法是将 DLL 放在一个单独的 AppDomain 中,以尝试删除它。我卸载了另一个 AppDomain,然后从磁盘中删除了 DLL。

如果您正在寻找一种执行更新的方法,那么我想我会选择一个生成真正 AppDomain 的存根 exe。然后,当该存根 exe 检测到要应用更新时,它会退出另一个 AppDomain,然后执行更新魔法。

编辑:更新程序不能与它正在更新的东西共享 DLL,否则它将锁定这些 DLL,从而防止它们被删除。我怀疑这就是为什么您仍然会遇到异常的原因。更新程序必须是独立的,并且不依赖于其他 AppDomain 使用的任何内容,反之亦然。

【讨论】:

  • 同意,这是我知道的唯一方法。
  • 我也会支持这个。我使用的许多较新的应用程序(Paint.NET、FileZilla)都有一个单独的应用程序启动来执行更新,这将调用卸载程序来删除应用程序,然后重新安装新的应用程序。在您的情况下,您可以让它删除 DLL,然后替换。
  • 我同意 - 我们在这里处理两个方面。
  • 在单独的 AppDomain 中粘贴代理库仍然会引发删除异常
【解决方案2】:

Unwrap 会将对象类型的程序集加载到调用它的 appdomain 中。解决此问题的一种方法是在您的“基本”程序集中创建一个调用 command.run 的类型,然后将其加载到新的 appdomain 中。这样,您就不必从不同程序集中的类型中对对象调用 unwrap,并且可以删除磁盘上的程序集。

【讨论】:

    【解决方案3】:

    当我构建一个自我更新的应用程序时,我使用了存根的想法,但存根就是应用程序本身。

    应用程序将启动,查找更新。如果它找到更新,它会将新应用程序的副本下载到临时存储,然后使用显示“您正在更新”的命令行选项启动它 (System.Diagnostics.Process.Start())。然后原始的exe退出。

    生成的 exe 启动,发现它是一个更新,并将自身复制到原始应用程序目录。然后它从该新位置启动应用程序。然后生成的 exe 结束。

    从原始应用安装位置新启动的 exe 启动 - 看到临时文件并将其删除。然后恢复正常执行。

    【讨论】:

      【解决方案4】:

      您始终可以使用MOVEFILE_DELAY_UNTIL_REBOOT 在重新启动时删除。这很可能是做这类事情的最简单的方式,通过 hackey 我通常会看到类似的东西;加载新的 DLL 或注入 explorer.exe 甚至修补系统 dll 以加载到另一个进程等...

      MoveFileEx From MSDN;

      lpNewFileName [in, optional] 新的 文件或目录的名称 本地计算机。

      移动一个文件时,目的地 可以在不同的文件系统上或 体积。如果目的地在 另一个驱动器,您必须设置 MOVEFILE_COPY_ALLOWED dwFlags 中的标志。

      移动目录时, 目的地必须在同一个驱动器上。

      如果 dwFlags 指定 MOVEFILE_DELAY_UNTIL_REBOOT 和 lpNewFileName 为 NULLMoveFileEx 注册 lpExistingFileName 文件 被删除当系统 重新启动。如果 lpExistingFileName 指的是 到一个目录,系统删除 仅在重新启动时的目录 目录为空。

      【讨论】:

      • 哇,这太晦涩难懂了,谢谢。当然,在启动时检查最新版本也是一样的,这就是我目前正在做的事情
      猜你喜欢
      • 1970-01-01
      • 2014-10-16
      • 2020-01-10
      • 1970-01-01
      • 2021-03-22
      • 2015-02-13
      • 2021-04-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多