本鱼拟成立工作室承接项目开发/软件定制/云设施开发运维/办公设备技术支持等,如您有相关需求,欢迎来询 | ::博客文章推荐::

.NET应用程序快速自动升级类库 SimpleUpdater 更新 4.0.0 版

: 原创作品 木魚 9441℃ 2评论

SimpleUpdater for .NET 是一个适用于.NET的快速自动更新类库,用于快速地为现有的.NET应用程序添加上自动更新功能。

功能特点

  • 简单易用
  • 支持增量更新等大量更新选项

更新详情

  • 【客户端】增加自定义引用接口 IUpdateNotify 以及 UsingAssembly() 函数,可在正式更新后依然调用自己的处理事件
  • 【客户端】增加 UsingFormUI() 函数以及更新对话框基类,可以使用自己的更新界面完全替换内置界面
  • 【客户端】修改WebClient初始化流程,避免后续下载包时发出的请求没有UserAgent标头
  • 【客户端】修正丢失的资源文件,避免导致命令行版无法使用
  • 【客户端】变更config文件配置
  • 【客户端】安装文件各操作中也支持报告进度

新增加的功能已自带Demo,请参见博客以及Demo目录下的相关项目。下一节将会做介绍。

新增的自定义接口以及自定义界面使用方法

1.自定义接口

曾经有人对我提出批评,说提供了那么一大堆事件但是却基本上都没法捕捉,等于没用。其实这个无法被捕捉的原因是,当你确认更新后,自动更新库会将自己复制到临时目录并单独新开一个进程进行更新,否则因为文件占用,是无法完成更新的。虽然这么解释了,但事件那么丰富只能给更新库自己使用,还是未免太浪费了。所以从4.0版本开始,引入了自定义接口。

自定义接口为 FSLib.App.SimpleUpdater.Defination.IUpdateNotify 。当你的任何类实现了这个接口之后,你都可以将这个类所在的程序集注册到 Updater 的实例中(通过  UsingAssembly 方法)。
在这之后,当正式更新开始,自动更新客户端会将这个接口所在的程序集以及所有引用的程序集全部一起复制到临时目录下,然后实例化这个接口,并进行初始化调用。此时,你便可以挂钩所有相关的事件了。

提醒:由于存在文件复制过程,因此建议将实现此接口的类定义在单独的较小的程序集中,避免放在主程序集等具有大量依赖的程序集中。一旦引用复制失败,将会导致自动更新客户端忽略此接口所在的程序集调用。
同时,实现此接口的类被实例化时,所在的路径是临时目录下,而不是程序所安装的目录,切记切记。

以下代码可参见完整包的Demo目录下的CustomeAssemblyDemo项目。

首先实现一个IUpdateNotify接口。

	/// <summary>
	/// Description of CustomConnect.
	/// </summary>
	public class CustomConnect:FSLib.App.SimpleUpdater.Defination.IUpdateNotify
	{
		public CustomConnect()
		{
		}

		#region IUpdateNotify implementation

		public void Init(FSLib.App.SimpleUpdater.Updater updater)
		{
			System.Windows.Forms.MessageBox.Show("已连接。当前更新程序的临时路径为:"+System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location));
		}

		#endregion
	}

然后使用Updater的实例方法进行注册。

//获得当前的更新实例
var updater=FSLib.App.SimpleUpdater.Updater.Instance;

/* 
 * 1.注册程序集。当程序集被注册的时候,任何程序集中实现了 FSLib.App.SimpleUpdater.Defination.IUpdateNotify 接口的都将会被自动实例化并调用
 *   通过此方法可以实现自己的事件捕捉以及处理类
 *   此例中, 类 CustomConnect 将会被实例化并调用
 */
updater.UsingAssembly(System.Reflection.Assembly.GetExecutingAssembly());

编译运行,便可以看到 CustomConnect 被成功实例化并调用了。

QQ20150507230821

 

2.自定义界面

自定义界面依赖于上一个功能,并更进一步,可以替换所有内置的对话框,并改用自己的对话框和界面交互来实现,与此同时,依然不需要关心底层的任何细节。

提示:由于依赖于上一个功能,因此注意要素完全一致。如果设计高度复杂且依赖较多的程序集,可能会导致调用失败。发现失败的时候,可通过写日志来找到问题出现的原因。

先创建一个默认的窗口,上面放一个 Dock 设置为 FillLabel,然后将继承的基类从 Form 修改为 FSLib.App.SimpleUpdater.Dialogs.AbstractUpdateBase (要用来替换的界面必须是基于 FSLib.App.SimpleUpdater.Dialogs.AbstractUpdateBase 派生的子类)。

以下代码仅仅用做演示。此基类中包含了大量的On开头的虚方法,提供了从检测更新到更新结束各个流程的状态和进度信息,可通过查看源代码获得完整的列表。此处仅用作演示。

protected override void OnPackageDownload(FSLib.App.SimpleUpdater.PackageEventArgs e)
{
	base.OnPackageDownload(e);
	
	label1.Text="正在下载 "+e.Package.PackageName+" ...";
}

protected override void OnUpdateFinished()
{
	base.OnUpdateFinished();
	
	label1.Text="更新成功!";
}

protected override void OnInstallUpdate()
{
	base.OnInstallUpdate();
	label1.Text="正在安装更新...";
}

protected override void OnRequestCloseApplication(FSLib.App.SimpleUpdater.QueryCloseApplicationEventArgs e)
{
	label1.Text="正在关闭程序..";
	
	//取消屏蔽下面这行,则会进行默认的处理(询问或自动关闭,依据更新信息的要求来)。如果屏蔽,则必须自己处理进程,并设置 e.IsCancelled 的值。
	//base.OnRequestCloseApplication(e);
	
	foreach (var p in e.Processes) {
		p.Kill();
	}
	//如果需要自定义处理,那么处理完成后一定要赋予一个值,否则会导致更新库对此处的值保持等待。
	//设置为false表示正常结束。返回true则表明出现了问题,要求取消更新
	e.IsCancelled=false;
}

protected override void OnRemoveFiles()
{
	label1.Text="正在移除旧文件...";
	base.OnRemoveFiles();
}
protected override void OnRemoveFile(FSLib.App.SimpleUpdater.FileInstaller.InstallFileEventArgs e)
{
	label1.Text="正在删除 "+e.Source;
	base.OnRemoveFile(e);
}

protected override void OnInstallFile(FSLib.App.SimpleUpdater.FileInstaller.InstallFileEventArgs e)
{
	base.OnInstallFile(e);
	label1.Text="正在安装 "+e.Source;
}

protected override void OnDecompressPackage(FSLib.App.SimpleUpdater.PackageEventArgs e)
{
	//Package有可能为null因为这个事件比较特殊,在所有的包开始解压缩之前会提前触发一次用作提醒,此时是没有包的。
	if(e.Package==null)
		return;
	
	label1.Text="正在解压缩 "+(e.Package.PackageName??"");
	base.OnDecompressPackage(e);
}

protected override void OnError(Exception ex)
{
	label1.Text="ERROR:"+ex.ToString();
	base.OnError(ex);
}

最后在更新前使用 UsingFormUI  来注册这个界面类。

//获得当前的更新实例
var updater=FSLib.App.SimpleUpdater.Updater.Instance;

/*
 * 2.自定义界面UI。此调用将会替换掉默认的更新界面(此例中将会把更新界面替换为 MainForm)
 *   和上面的使用方法类似,但可实现完全自定义的效果
 *   要用来替换的界面必须是基于 FSLib.App.SimpleUpdater.Dialogs.AbstractUpdateBase 派生的子类
 */
updater.UsingFormUI<MainForm>();

编译并运行,会看到更新进度对话框已经是另外调用的UI了。

QQ20150507230833

安装方式

以下安装方式任选其一即可:

  • (推荐) 使用Nuget包管理器,搜索“iFish” 后找到 “iFish's Simple Application Updater Library”(fishlee.net.simpleupdater) 并安装即可。包中不包含文档,如果您需要文档和手册,请下载完整包。
  • 可以通过下载完整包后引用相关的文件(客户端目录下),推荐引用DLL。EXE模式不推荐,仅推荐其用作命令行模式更新。

相关地址

开源地址

SimpleUpdater on GITHUB

喜欢 (0)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
(2)个小伙伴在吐槽
  1. 木鱼,请问要升级完成后如何让程序重新启动?

    xgq0072017-11-02 17:34 回复
  2. FSLib.App.SimpleUpdater.FileInstaller”中不存在类型名

    xwanger2017-03-28 11:54 回复