简化了.NET中的应用程序更新

时间:2011-12-08 06:05:12

标签: c# deployment

自动更新桌面应用程序似乎是.NET中的一个难题。从microsoft的clickonce到各种开源和付费解决方案,有许多解决方案。所有这些模式都是:

1检查远程服务器以查找要运行的版本
 2下载新版本
 3打开包装到临时文件夹
 4启动一个填充程序,在应用程序关闭后用新的替换旧文件  5杀死正在运行的应用程序,以便垫片进程可以开始工作
 6重新启动主应用程序

这个过程似乎有许多活动部分和失败点。但是,您可以将应用程序编写为一个下载并执行远程dll的简单循环。这似乎避免了自动更新应用程序所涉及的许多复杂性,例如用户权限,uac,防病毒程序等。

这对我来说似乎是坚实的,也是未来的。我的应用程序不需要很多大型支持文件,所以我不应该使用这种方法吗?有没有办法可以犯这种错误?如果是这样,这些复杂性与其他自动更新解决方案的复杂性相比如何?

例如:

Thread helper;
int currentVersion=0;

static void Main()
{
  //dumb loop, functions as a loader
  while(true)
  {
      var remoteVersion = GetRemoteVersion();
      if(remoteVersion > currentVersion)
      {
         if(helper != null)
         {
            //kill thread gracefully :)
         }

         currentVersion = remoteVersion;
         byte[] bytes = GetRemoteDllAsByteArray();
         var asm = Assembly.Load(bytes);
         var t = asm.GetType("a known type with a static method called Start()");
         var mi = t.GetMethod("Start");

         //run this on a helper thread outside the main loop:
         // the start method is the entry point to your application
         helper= new Thread(() => mi.Invoke(null,null));
         helper.SetApartmentState(ApartmentState.STA); //for winforms/wpf
         helper.Start();
      }


      Thread.Sleep(1 day);//only check for new versions once a day
  }   
}

我的示例中的额外复杂性是您必须将所有依赖项打包为已下载的dll中的资源,但可以将其设置为构建步骤,并避免弄乱用户的文件系统。

1 个答案:

答案 0 :(得分:1)

你的解决方案应该有效,如果你想保持简单,这似乎是一个很好的方法。

注意

您应该在另一个域中加载程序集,因为如果您更新应用程序,则会在相同的名称空间中加载相同的类型。这会导致冲突。另一种方法是重新启动您的应用程序。

依赖关系

您不需要将所有依赖项打包为资源。使用下载,解压缩(zip)并包含所有程序集的二进制文件。

为此,您可以使用简单的方法(打包/解压缩):

  • 写入/读取(客户端)程序集的名称
  • 将二进制文件的字节大小写入/读取为Int32
  • 将程序集的字节写入文件/读取程序集的字节并将其写入磁盘或自定义文件系统
  • 继续此操作,直到打包/解压缩每个文件

在解析依赖关系时,您可以使用类似于此示例的内容:Assembly loaded using Assembly.LoadFrom() on remote machine causes SecurityException

更新

还可以使用此系统为每个版本更新创建更新包(例如1.0 -> 1.51.3 -> 1.5)。如果首先检查已弃用的文件并为每个版本更新创建一个包,这可以避免大量流量。