在编写自己的自动更新程序时,是否有一个我应该遵循的通用框架?
前一段时间我正在阅读如何创建一个'boot strapper',它将在主应用程序之前首先加载(因为由于文件锁等而无法更新正在运行的应用程序。)
所有针对此的提示/最佳做法?
答案 0 :(得分:16)
你可能要写自己的。正如FOR提到的,基本的想法是在服务器上放置程序的最新版本(我假设是EXE),然后在启动时让应用程序检查服务器,如果是的话,从服务器下载EXE。更新的版本。
我通常将其实现为应用程序在启动时调用的Web服务。关于这种方法的几个警告:
Web服务方法需要获取服务器上EXE的版本号,并将其与调用者的版本号进行比较。如果使用Assembly类读取服务器EXE的版本号,则只要Web服务实例正在运行(至少20分钟),就会锁定该文件。因此,您有时可能无法使用较新版本替换服务器上的EXE。使用AssemblyName类 - 这允许您在不加载程序集的情况下读取程序集信息(并将其锁定)。
调用者应用程序无法用新版本替换自己的文件 - 您无法删除或更新正在运行的应用程序文件。然而, 可以做的是在运行时重命名自己的文件。因此,自动更新的技巧是让应用程序重命名(例如“MyApplication.exe”到“MyApplication_OLD.exe”),将新版本下载到应用程序文件夹(名为“MyApplication.exe”),通知用户发生了更新,需要重新启动应用程序,然后结束。当用户重新启动应用程序时,它将是启动的较新版本 - 此版本检查并删除旧版本。
执行自动更新,在这样的更新后自动重启应用程序是非常棘手的(它涉及启动另一个进程,然后在自动重启过程开始之前结束自己的进程)。我从来没有让用户抱怨不得不重启应用程序。
答案 1 :(得分:11)
好的,首先,如果市场上的安装程序/更新程序产品之一符合您的需求,您应该使用它们。 话虽这么说,我很幸运不久前建立了这样一个系统。 是的,我们的安装程序/更新程序包括客户端的两个部分,以便:
~A部分将连接到存储和发布最新版本的服务器;如果有更新版本的B部分可用,它会下载并启动它
~B部分将专注于安装/更新实际应用程序(并可以下载和安装A部分的更新)。
除此之外,我建议始终考虑安装程序/更新程序中的以下4个操作:
安装和卸载
更新和回滚(即撤消上次更新)
当您的用户拥有一个可以在一夜之间自动更新的系统时,回滚功能非常重要..如果每次更新都会更新,他们可以在您修复问题时回滚并继续工作。
最后,安装程序/更新程序应该尝试并且不知道它安装/更新的应用程序,这样,当该应用程序发生更改时,安装程序/更新程序系统受到的影响最小。
答案 2 :(得分:3)
我为我在C ++中使用的应用程序编写了一个更新程序,但总体结构是相同的。
这对我们来说效果很好,因为它总是下载一个新的“更新程序”作为它做的第一件事,我们可以处理一些可能不起作用的时髦新事物。
答案 3 :(得分:3)
写了我们自己的自动更新软件。所以这是我的小费......不要这样做!当然,这完全取决于您的具体情况,但这是我公司遇到的问题:
我们的软件存在的问题是我们需要在所有Windows平台上提供大量的灵活性和支持。我们编写的解决方案运行良好,但是当Windows版本发生变化或者与我们实验室中的版本不同时,它们没有扩展并开始失败。我们最终购买了软件,我建议你也这样做。如果您有兴趣,我们购买了一款名为AutoUpdate +(link text)的产品。
答案 4 :(得分:3)
这是我为满足WinForms和WPF应用程序的特定需求而编写的开源解决方案。一般的想法是尽可能以最低的开销获得最大的灵活性。
所以,集成非常容易,而且库可以为您完成一切,包括同步操作。它也高度灵活,让您确定要执行的任务以及在什么条件下 - 您制定规则(或使用已经存在的规则)。最后一点是对任何更新源(web,BitTorrent等)和任何 Feed格式的支持 - 任何未实现的内容,您都可以自己编写。
还支持冷更新(需要重启应用程序),并自动完成,除非为任务指定了“热交换”。
这可以归结为一个DLL,大小不到70kb。
http://www.code972.com/blog/2010/08/nappupdate-application-auto-update-framework-for-dotnet/
的更多详情代码位于http://github.com/synhershko/NAppUpdate(根据Apache 2.0许可证授权)
我计划在我有更多时间的时候扩展它,但老实说,你应该能够自己快速增强它,无论它目前不支持什么。
答案 5 :(得分:2)
ClickOnce对我们来说效果不佳。我们在客户的服务器上安装数据库。在我们进行更新之前,需要更新其末尾的数据库。我们有超过2或3个客户,所以为我们的应用程序做ClickOnce并不是最好的主意,除非我遗漏了ClickOnce的重要内容。
我所做的是在数据库中添加一个字段以获取版本号。在我们的ftp站点上,我有一个版本文件夹,其中包含我们应用程序的每个版本号的文件夹。在该特定版本的文件夹中,我们放置了一个zip文件,其中包含setup.exe和setup.exe将启动的msi文件。所有预先请求都是从供应商网站下载的,以确保我们的FTP站点不会受到大量下载(.Net 3.5,当我们转移到它时)。当我们的应用程序启动时,它会检查数据库中的字段是否有版本号,如果它与当前版本的程序集版本不同,它将连接到ftp站点,从该新版本的文件夹下载zip文件,解压缩,以及执行设置。这将安装较新版本的.Net或我们可能添加的任何其他要求,然后启动MSI以安装我们的应用程序,用户只需点击几下即可。
答案 6 :(得分:1)
如果您正在使用.Net,为什么不使用ClickOnce?它将完成您开箱即用的所有操作,并且几乎不需要设置。
答案 7 :(得分:1)
此zip包含单词搜索生成器工具的源代码,其中包含AppUpdater样板代码 http://cid-842434ebe9688900.skydrive.live.com/self.aspx/Games/WordSearchGenerator-src-v1.3.zip
查找名称中包含“AppUpdater”的3个源模块。
它非常简单,仅适用于单组装应用程序。没有MSI文件。只是一个EXE。哲学是更新检查自动发生,但只有在用户确认后才会安装更新。
更新程序的工作方式:
它从包含“最新版本”信息的URL加载XML文档,以及实际新版本所在的第二个URL。更新程序逻辑验证XML文档上的签名,但您可能不关心它。然后,更新程序将当前版本与最新版本进行比较,并且可以告知应用程序是否有可用的更新。更新程序还处理替换就地问题。
在此模型中,更新期间应用程序有三个“生命周期阶段”。在正常过程中,应用程序检查更新,然后正常运行。在某些时候,用户可能确认他们想要安装可用更新,并且更新程序将应用程序下载到临时位置,然后使用新下载的exe启动进程。然后更新程序逻辑退出第一个进程。第二个进程基于第一个进程赋予它的命令行参数,意识到它是一个新下载的副本,需要自我复制。它将自身复制到原始位置(在命令行中指定),启动 exe,然后退出。第三个进程正常启动,发现有更新,并删除temp exe副本。然后它正常运行,包括检查更新。它会发现没有更新,然后就会正常运行。这涵盖了就地更新逻辑的操作。
这些都是由Windows窗体或WPF窗口的构造函数中的这些行处理的:
_Updater = new AppUpdater.SimpleAppUpdater(_MyManifestUrl);
_Updater.Startup(App.CommandLineArgs);
check-for-update问题也由构造函数中的几行代码处理,它们创建并运行后台工作线程:
_Worker = new System.ComponentModel.BackgroundWorker();
_Worker.DoWork += CheckLatest;
_Worker.RunWorkerCompleted += CheckCompleted;
_Worker.RunWorkerAsync();
CheckLatest是这样的:
void CheckLatest(object sender, System.ComponentModel.DoWorkEventArgs e)
{
lock (_Updater)
{
if (_Updater.UpdateIsAvailable) // Checks for update
{
// can update a textbox (etc) here. Be careful of InvokeRequired.
}
}
}
完成的活动是:
void CheckCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
if (!e.Cancelled && e.Error == null)
{
lock (_Updater)
{
// only display the about box if there is an update available.
if (_Updater.HaveCheckedForUpdate && _Updater.UpdateIsAvailable)
{
// do whatever you want here. Eg, pop a dialog saying
// "an update is available"
About about = new About();
about.Message= "An update is available";
about.ShowDialog();
}
}
}
}
它适用于WinForms或WPF应用程序。我想它也适用于控制台应用程序,但我从未尝试过。
创建(可能签名的)清单文件是一项单独的任务,此处未涉及。
考虑到这一点,最好将其打包为基类AutoUpdatingForm(适用于WinForms)或AutoUpdatingWindow(适用于WPF)。但我从未迈出这一步。
答案 8 :(得分:0)
十年前我写了一个自动更新程序(不是在.NET中),但它的要点是应用程序有一个在启动时检查的版本ID。在这种情况下,应用程序查询具有当前版本的数据库表,如果运行版本小于当前版本,则提示用户下载最新版本。通过检查URL可以完成同样的事情。
答案 9 :(得分:0)
我还没有尝试的解决方案之一就是拥有一个可以在静默模式下运行的安装程序。
应用程序调用服务器,如果需要更新,它会下载最后一个安装程序,然后使用静默或更新标志运行它。
它有很多好处: