如何在没有主程序重启的情况下更新dll文件?

时间:2018-01-31 09:16:40

标签: c# .net dll

如何在没有程序重启的情况下更新dll文件?

我想创建我的"更新程序"类。它的主要思想是      检查本地(连接到执行文件)和服务器DLL文件,      当有更新的版本时,将服务器文件复制到本地。

代码:

Updater updater = new Updater(LOCAL_PATH, SERVER_PATH);
if (updater.IsAvailableNewerVersion)
    updater.Update();

更新程序的ctor采用两条路径 - 服务器dll和本地dll并计算其版本。      然后我调用一个属性IsAvailableNewerVersion - 如果它是真的(可用版本比本地更新),我调用Update方法。      更新方法的主要思想是将服务器dll文件复制到本地并覆盖,并告诉用户重启程序。

代码:

public class Updater
{
    private readonly string _localPath;
    private readonly string _serverPath;
    private readonly Version _currentVersion;
    private readonly Version _availableVersion;

    public Updater(string localPath, string serverPath)
    {
        _localPath = localPath;
        _serverPath = serverPath;
        _currentVersion = AssemblyName.GetAssemblyName(_localPath).Version;
        _availableVersion = AssemblyName.GetAssemblyName(_serverPath).Version;
    }
    public bool IsAvailableNewerVersion => _availableVersion.Major > _currentVersion.Major ||
                                           _availableVersion.MajorRevision > _currentVersion.MajorRevision ||
                                           _availableVersion.Minor > _currentVersion.Minor ||
                                           _availableVersion.MinorRevision > _currentVersion.MinorRevision ||
                                           _availableVersion.Build > _currentVersion.Build ||
                                           _availableVersion.Revision > _currentVersion.Revision;
    public void Update()
    {
        try
        {
            File.Copy(_serverPath, _localPath, true);
        }
        catch (Exception e)
        {
            MessageBox.Show("Unable to copying file - " + e);
            return;
        }
        MessageBox.Show("File was successfully updated. Please restart program.");
    }
}
  1. 有没有办法在使用之前检查dll文件?
  2. 如何在没有程序重启的情况下更新dll文件?
  3. P.S。 我认为使用服务器DLL文件,但我的程序依赖于服务器不好。

2 个答案:

答案 0 :(得分:3)

您无法在正在运行的应用程序域中卸载/更改程序集;所以基本上你有两个选择:

  1. 使用执行此工作的启动程序exe并调用内部 exe来执行实际工作,在完成时关闭它(在关闭之前或之后启动新的工作)
  2. 在单个exe中使用多个app-domains,隔离每个加载的位置
  3. 第二种方法对服务器应用程序更有用,因为您可以将外部exe和漏斗请求中的网络IO处理到内部app-domain,只需将单个引用更改为两个系统之间的交换。但是,app-domains不在.NET Core中,因此您应该意识到它限制了您的灵活性。

答案 1 :(得分:0)

<强> 1。有没有办法在使用之前检查dll文件?

如果您使用单个EXE,则取决于您使用DLL的方式。如果它们与您的应用程序紧密耦合,我不知道如何这样做。

但是如果DLL只是实现核心DLL的接口,你可以使用以下命令加载它们:

Assembly assembly = Assembly.LoadFrom("path\orbital.dll"));
Type type = assembly.GetType("FullClassName");
object instanceOfMyType = Activator.CreateInstance(type);

这要求您遵循一些设计模式,这对您的应用程序有利。但是,如果您已经有多个强耦合的DLL(这意味着,您在Visual Studio项目中将它们添加为引用并且正在创建var object = new YourOtherDLLNamespace.YorObjectInTheOtherDLL()对象),那么您可能需要花费大量时间来更改此方法。 / p>

这种方法的好处是你可以在加载之前检查DLL版本,从服务器复制新版本(或你认为合适的任何其他方法),然后加载它。

<强> 2。如何在没有程序重启的情况下更新dll文件?

好吧,假设你就像我对第1项的建议一样。一旦你加载了DLL,你将无法卸载它。您可以使用垃圾收集器销毁所有对象,但这不会改变窗口加载它的方式。

所以单个EXE的基本答案是否定的。

其他解决方案

你可以将你的解决方案包装在不断检查DLL是否更新的其他EXE中,发送一个自定义事件(这样你的应用程序EXE现在会在关闭它之前采取适当的行动),通知用户并且,如果用户想要这样做,那么您可以关闭该应用程序。然后你的其他app包装器会更新它并再次启动EXE。