我有一个.exe程序集和一组引用的程序集,我希望能够部署更新的代码。我不需要实际更改运行代码,但下次启动可执行文件时,我希望它能够获取更新后的代码。目前,当我尝试复制正在运行的文件时,出现有关另一个进程正在使用的.exe文件的错误。如何更新正在运行的c#进程(AKA热部署)的程序集?
总结;如何在.exe正在使用时更新代码?
我有一个.exe程序集和一组引用的程序集,我希望能够部署更新的代码。我不需要实际更改运行代码,但下次启动可执行文件时,我希望它能够获取更新后的代码。目前,当我尝试复制正在运行的文件时,出现有关另一个进程正在使用的.exe文件的错误。如何更新正在运行的c#进程(AKA热部署)的程序集?
总结;如何在.exe正在使用时更新代码?
这很容易做到。您可以重命名该文件,Windows对该句柄有一个锁定,而不是该文件的目录条目。现在您可以复制更新而没有问题。剩下要做的就是在应用程序重新启动后摆脱重命名的文件。如有必要。
我不认为这是可能的。例如,在零宕机时部署asp.net应用程序时,最佳做法是使用负载平衡器,以便取下一个实例,更新它,然后取下另一个实例进行更新。
装配体在使用中时无法更新。这种情况的最佳选择是制作一个小的可执行文件,它执行程序集的阴影副本,并从新位置启动它们。
这样,当用户启动程序时,您可以从部署站点复制(本地)复制,该复制始终可以被覆盖。
ClickOnce给你一些选择。 “应用程序启动后更新”有update strategy。
对于更复杂的场景,有System.Deployment namespace。例如,您可以定期轮询应用程序中的更新。
只是一个想法:尝试MEF和[导入[ “http://someRemoteResource”]]
有关以下内容:
最好的想法应该是已经提出的其他答案之一...就像使用MEF和/或ClickOnce进行重构一样。但是,这些解决方案无法帮助您进行“部署”。他们要求您对exe文件进行更改,或者创建引导程序可执行文件,这只会帮助您进行下一次部署。
对于此部署你可以尝试这样做(我从来没有这样做过,但理论上它可以工作):
RunOnce键包含命令行命令,它们在重新启动时运行一次,然后从注册表中删除,以便它们不会再次运行。这就是InstallShield如何允许您在其他应用程序正在使用时覆盖某些dll的方式。
本课程将重新命名当前运行的可执行文件,如果它完成无一例外,你可以简单地写入新的可执行文件,然后重新启动,如:
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;
}
}
似乎有一个Codeplex项目针对.NET的热部署。我还没有尝试,但:http://hotdeploy.codeplex.com/ – 2010-02-25 16:48:49