我已经编写了一个程序,如果它在服务器上找到更新的版本就会更新自己,但我发现很难干净地实现它。
检查远程服务器并下载文件很简单但是那又如何呢?它不能简单地File.Copy(“newversion.exe”,“myprogram.exe”),因为myprogram正在运行且文件被锁定。
我是通过下载两个文件newversion和更新来实现的。 myprogram然后启动更新并退出。 更新等待两秒钟,复制,然后启动myprogram(现在是更新版本)并退出。 myprogram在启动时查找更新并删除它,如果找到则返回newversion。 mypogram现在是新版本,没有留下文件。
必须有一种比这更好的方法,那么程序更新自己的.net方式是什么?
PS。很抱歉,如果这个问题出现两次 - 我第一次提交时会出现'堆栈溢出已损坏'页面。
答案 0 :(得分:15)
查看ClickOnce Deployment是否能满足您的需求。
答案 1 :(得分:7)
我看了Wix和ClickOnce并且不喜欢他们。对于单文件“xcopy部署”类型的WPF应用程序,我想要更简单的东西。
所以我建了一个。这是一个AppUpdater类,您可以将其放入任何WPF应用程序中,并在必要时自动更新。
检查版本号并下载最新版本很容易。
下一部分不太容易。你如何替换正在运行的应用程序?我采取的方法是:
每次运行时,应用程序都会检查一个众所周知的URL版本。如果版本不晚于当前正在执行的应用程序的版本,则没有其他任何事情要做。
如果以后版本为IS,那么app会抓取一个名为Mutex,将自身(Assembly.GetExecutingAssembly()。Location)复制到临时位置,然后从该临时位置启动一个新进程(进程#2) ,传递一个命令行参数,说明“你正在尝试更新”并给出原始的exe位置。
进程#1自行关闭。
进程#2启动 - 它看到它正在尝试更新,因此它会下载更新的图像,并将其放在原始位置(在命令行上传递的位置)。它不是等待2秒或任何任意时间,而是使用命名的互斥锁来确定进程#1何时退出。
进程#2然后使用原始位置启动进程#3。
进程#2关闭,释放其名为Mutex。
进程#3启动。它会检查版本URL - 看到它是最新的。无需更新。进程#3还等待进程#2释放其Mutex,然后删除EXE的临时副本 - 进程#2使用的临时副本。
修改强>
回应评论,是的,这听起来很复杂。但是AppUpdater模块中所有这一切的逻辑。从WPF应用程序中使用它非常简单:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
// add this line in your constructor
if (UpdaterCheck()) this.Hide();
}
// this is all boilerplate
private Ionic.AppUpdater.Wpf.Updater _updater;
private string _manifestUrl = "http://example.org/AppUpdates/MyApplication/Manifest.xml";
private string _infoUrl = "http://example.org/MyApplication.html";
private string _description = "MyApplication is a delightful application; it does x, y, and z. ";
// Obtain the publicKey XML from the ManifestTool that ships with Ionic AppUpdater.
// The following string is Ionic's public key. You will need a different one.
// Consult the Readme for more information.
private string _publicKeyXml = "<RSAKeyValue><Modulus>sZqhvF0KX6m4blah..blah...=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
// add this boilerplate method
private bool UpdaterCheck()
{
_updater = new Ionic.AppUpdater.Wpf.Updater("This is MyApplication.",
_infoUrl,
_description,
_manifestUrl,
_publicKeyXml);
return _updater.Status.IsUpdating;
}
...
Details and code you can run, here。
它仅适用于WPF应用程序,但构建WinForms版本的东西非常简单。同样的想法,虽然生成UI的一些逻辑必须改变。
答案 2 :(得分:3)
答案 3 :(得分:2)
当你知道“解决方法”时很容易。您的程序无法自行下载,因为该文件已被正在运行的进程锁定。解决方法是仍然可以重命名该文件。所以这就是你做的:
如果您的程序名称是“myprogram.exe”:
这将允许您在没有外部更新程序的情况下更新程序。
答案 4 :(得分:0)
您可能需要查看.NET's No Touch Deployment。它至少在市场营销中被Click-Once取代。
我写了一个使用它的应用程序。它从本地Intranet服务器中取出了它的程序集。它使用套接字来侦听特定端口,因此我可以通过发送消息来强制升级,这会生成另一个程序来杀死它/重新启动它。可能不是最好的解决方案,但它有效。
我说Click-Once是一个更好的解决方案,但我想我会提到No Touch。