2010-02-25 59 views
12

我有一个.exe程序集和一组引用的程序集,我希望能够部署更新的代码。我不需要实际更改运行代码,但下次启动可执行文件时,我希望它能够获取更新后的代码。目前,当我尝试复制正在运行的文件时,出现有关另一个进程正在使用的.exe文件的错误。如何更新正在运行的c#进程(AKA热部署)的程序集?

总结;如何在.exe正在使用时更新代码?

+0

似乎有一个Codeplex项目针对.NET的热部署。我还没有尝试,但:http://hotdeploy.codeplex.com/ – 2010-02-25 16:48:49

回答

17

这很容易做到。您可以重命名该文件,Windows对该句柄有一个锁定,而不是该文件的目录条目。现在您可以复制更新而没有问题。剩下要做的就是在应用程序重新启动后摆脱重命名的文件。如有必要。

+0

你可以提供更多的细节/代码? – Jerry 2013-04-29 13:23:34

+0

除了答案之外,您可能还要注意,在重命名文件之前,用户可能需要首先从调试过程中分离,否则IDE(即Visual Studio)将不允许编辑源文件。 – 2014-03-18 18:00:12

+0

这是不好的解决方案,因为重命名后你将会损坏快捷方式。您应该使用帮助器应用程序。 – l0pan 2017-02-28 22:52:58

3

我不认为这是可能的。例如,在零宕机时部署asp.net应用程序时,最佳做法是使用负载平衡器,以便取下一个实例,更新它,然后取下另一个实例进行更新。

2

装配体在使用中时无法更新。这种情况的最佳选择是制作一个小的可执行文件,它执行程序集的阴影副本,并从新位置启动它们。

这样,当用户启动程序时,您可以从部署站点复制(本地)复制,该复制始终可以被覆盖。

1

有关以下内容:

  1. 部署的exe到更新的文件夹。
  2. 每当应用程序启动,它会 检查更新文件夹。
  3. 如果它不是空的,执行复制 程序
  4. 的复制程序将随后更换 与一个在 更新文件夹
  5. 在更新文件夹中删除任何
  6. 然后重新启动该exe现有的EXE
1

最好的想法应该是已经提出的其他答案之一...就像使用MEF和/或ClickOnce进行重构一样。但是,这些解决方案无法帮助您进行“部署”。他们要求您对exe文件进行更改,或者创建引导程序可执行文件,这只会帮助您进行下一次部署。

对于此部署你可以尝试这样做(我从来没有这样做过,但理论上它可以工作):

  1. 复制新的DLL到子文件夹的地方
  2. 添加一个命令line xcopy命令到RunOnce registry key将新的dll从子文件夹复制到最终的exe文件夹中您想要的位置。
  3. 重新启动。

RunOnce键包含命令行命令,它们在重新启动时运行一次,然后从注册表中删除,以便它们不会再次运行。这就是InstallShield如何允许您在其他应用程序正在使用时覆盖某些dll的方式。

0

本课程将重新命名当前运行的可执行文件,如果它完成无一例外,你可以简单地写入新的可执行文件,然后重新启动,如:

Ourself.Rename(); 
// Download or copy new version 
File.Copy(newVersion, Ourself.FileName()); 
// Launch new version 
System.Diagnostics.Process.Start(Ourself.FileName()); 
// Close current version 
Close(); // Exit(); 

简单就够了吗?

class Ourself 
{ 
    public static string FileName() { 
     Assembly _objParentAssembly; 

     if (Assembly.GetEntryAssembly() == null) 
      _objParentAssembly = Assembly.GetCallingAssembly(); 
     else 
      _objParentAssembly = Assembly.GetEntryAssembly(); 

     if (_objParentAssembly.CodeBase.StartsWith("http://")) 
      throw new IOException("Deployed from URL"); 

     if (File.Exists(_objParentAssembly.Location)) 
      return _objParentAssembly.Location; 
     if (File.Exists(System.AppDomain.CurrentDomain.BaseDirectory + System.AppDomain.CurrentDomain.FriendlyName)) 
      return System.AppDomain.CurrentDomain.BaseDirectory + System.AppDomain.CurrentDomain.FriendlyName; 
     if (File.Exists(Assembly.GetExecutingAssembly().Location)) 
      return Assembly.GetExecutingAssembly().Location; 

     throw new IOException("Assembly not found"); 
    } 

    public static bool Rename() 
    { 
     string currentName = FileName(); 
     string newName = FileName() + ".ori"; 
     if (File.Exists(newName)) 
     { 
      File.Delete(newName); 
     } 
     File.Move(currentName, newName); 
     return true; 
    } 
} 
相关问题