ClickOnce部署

需求

  • 普通项目生成Debug或者Release文件夹后,总不好把这个目录直接丢给客户。
  • 程序需要一些运行时支持,不同PC机上预装的环境也不同。
  • 我们可以制作安装包。
  • 我们的程序可能会存在某些隐性的bug,客户或许会有新的需求,我们会不断地修改程序。
  • 这样我们每次都要制作发布一次安装包,而客户每次都要点击N次"下一步"重新进行安装,很繁琐。
  • 我们可以考虑使用ClickOnce部署方式。

简介

  • Windows Installer由用户自身选择安装目录,默认安装在Program Files下,而ClickOnce程序则安装在ClickOnce缓存中。
  • ClickOnce缓存是"当前用户\Documents and Settings\Local Settings"目录下的一系列隐藏目录。
  • ClickOnce应用程序会显示在"添加/删除程序"控制面板选项上,与Windows Installer的应用程序一样。
  • ClickOnce应用程序所能占用的空间量受配额限制,配额限制了ClickOnce 缓存的大小。缓存大小应用于所有用户的联机应用程序,单个部分信任的联机应用程序最多只能占用配额空间的一半。安装的应用程序不受缓存大小的限制。对于所有 ClickOnce 应用程序,缓存只保留当前版本和前一个安装的版本。因此与普通的应用程序只能卸载不同,ClickOnce应用程序还可以选择回退到之前的版本。
  • 默认情况下,客户端计算机有250MB的存储区供联机ClickOnce应用程序使用。数据文件不计入该限制。系统管理员可以通过改变注册表项"HKEY_CURRENT_USER\Software\Classes\Software\Microsoft\Windows\CurrentVersion\Deployment\OnlineAppQuotaInKB"来修改此配额。该注册表项是一个用千字节表示缓存大小的DWORD值。例如,要将缓存大小减小到50MB,应该将该值更改为51200。

制作安装包

1、安装Installer Projects插件

Installer Projects插件

2、创建"Setup Project"项目

Setup Project

输入项目文件名:

输入项目文件名称

你可以通过添加"项目主输出",来添加应用程序,此时项目生成的EXE和相关DLL将会被添加到"Application Folder"中,也就是安装好程序之后的主目录:

添加项目主输出

这里选择的是你的启动项目:

项目主输出

点击"确定":

选择完项目主输出后

注意此时程序目录中,只有你程序生成的DLL和EXE文件,如果你的应用程序还需要相关的资源文件或者其它内容,需要在"Applcation Folder"上手动添加文件夹和所需文件,就像下面这样:

手动添加相应的资源文件

通常我们还会为用户创建桌面快捷方式:

创建快捷方式

将上一步生成的"Shortcut to 主输出..."拖拽到"User's Desktop"目录下:

创建快捷方式

选择它的属性进行修改:

修改快捷方式属性

从上到下分别是快捷方式的名称、备注以及图标。

  • 需要注意的是图标仅能从"Application Folder"中进行选取,如果你不想使用系统默认的程序图标,需要手动将图标文件添加到"Application Folder"中,再在属性里进行选择。
  • 如果你添加图标后,发现快捷方式的图标还是默认的系统图标,有可能是你添加的图片分辨率太大,系统加载不了(推荐32×32),也有可能是你主程序生成的exe没有选择程序图标。

选择应用程序图标

通常我们还会为用户准备一份卸载程序,这里我们需要用到"C:\Windows\System32\msiexec.exe",你可以直接使用C盘中的程序,生成的时候会提示一个警告:

'msiexec.exe' should be excluded because its source file 'C:\Windows\System32\msiexec.exe' is under Windows System File Protection

虽然无伤大雅,但仍然建议拷贝一份"msiexec.exe"出来到"Application Folder"下,然后我们创建它的快捷方式,并命名为Uninstall.exe,或者你喜欢的任意名称。

创建Uninstall

我们先去"安装项目"的属性窗口,需要注意这里的"属性"并非是"右键项目->属性"出来的属性窗,找到程序的ProductCode,拷贝下来。

回到我们的"Uninstall.exe"快捷方式的属性,在Arguments一栏填上"/x "加上面拷贝的ProductCode,注意两者之间中间有空格,如下图所示:

为Uninstall添加参数

至此,我们的安装程序和卸载程序就创建完毕,生成项目,可以看到两个文件,如下所示:

生成安装程序

其中"setup.exe"包括环境等一系列检查,推荐使用这个进行程序安装,而"*.msi"程序则安装的是程序的实体。

如果你还想给用户开始菜单中添加你程序和卸载的快捷方式的话,你只需重复上面的步骤,将两个快捷方式,拷贝到"User's Programs Menu"目录下即可,这里不再重复说明。

最后我们提一下,点击"安装项目->右键属性"中的属性页窗口,主要是在"Prerequesites"中选择你应用程序需要的环境支持:

先决条件

通常系统会为你选择最恰当的环境需求,当然你也可以根据你的实际需要进行配置。

ClickOnce部署示例

以下是一个显示当前程序版本的简单桌面应用程序(.net framework 4.8),程序实际代码如下所示:

public FrmShowVersion()
{
	InitializeComponent();
	txtCurVersion.Text = GetProgramVersion();
}

string GetProgramVersion()
{
	StringBuilder result = new StringBuilder();
	try
	{
		result.AppendLine($"程序集版本:{Assembly.GetExecutingAssembly().GetName().Version}");
		result.AppendLine();
		result.AppendLine($"文件版本:{Application.ProductVersion}");
		result.AppendLine();
		result.AppendLine($"部署版本:{ApplicationDeployment.CurrentDeployment.CurrentVersion}");
	}
	catch 
	{
		//未设置部署的相关信息时,想显示部署版本信息时会抛出异常
	}
	return result.ToString();
}

运行如下所示:

1.0版本运行效果

点击项目->右键选择属性->在标签页中选择"发布",进入发布窗口:

VS发布窗口

下面我们依次介绍:

  • 发布文件夹位置:可选项只有本地文件夹或者ftp服务器,演示的时候我们选择在本地新建一个文件夹:"D:\ClickOncePublish",这是给你自己发布程序用的。

发布文件夹位置

  • 安装文件夹URL(如果与以上不同):支持文件系统、FTP和IIS,实际我在测试的时候,设置为本地文件的时候不行,仅能支持网络共享文件夹。演示程序中,我们用IIS创建了一个网站,网站物理路径选的是发布文件夹的路径"D:\ClickOncePublish",如下所示:

自动更新网站

你可以根据你的实际应用环境换成共享文件夹或者ftp服务器,这是给客户安装和更新程序用的,这里我们选择刚创建好的网站作为安装和更新路径,如下图所示:

选择IIS站点作为程序安装和更新路径

  • 安装模式里我们选择脱机也能使用,联机选项我估计你没有Internet连接的时候会出问题,有兴趣的可以试一下。
  • 应用程序文件:让你设置哪些文件要生成,哪些文件不生成,如下所示:

应用程序文件

  • 系统必备组件:就是运行你这个程序需要什么环境支持,跟我们制作安装包的时候的Prerequisites一样,如下所示:

系统必备组件

  • 更新:就是设置各种更新的详细信息,默认是什么都没有选的,我们的演示程序如下设置:

程序更新设置

  • 选项:这里设置程序的说明信息,这里我们选上了部署网页,你还可以在清单里勾上"创建桌面快捷方式":

发布选项

  • 随每次发布自动递增修订号:默认是勾上的,你也可以根据你的实际情况直接修改版本号。

  • 发布向导:就是把上面的部分必要的设置过程用向导的方式让你填写,值得一提的是,如果你试图在这里把更新位置选成本地文件夹,会得到一个错误信息:

发布向导报错

  • 设置完成后,你就可以在这里点击"立即发布",或者在项目上右键选择"发布",如果你配置了显示发布网页,则会弹出如下的网页:

发布成功

  • 此时发布目录里的文件如下所示,其中"*.application"是程序实体,而"setup.exe"在安装前会进行环境检查:

发布目录里的文件

安装环境检查

程序实体安装

  • 安装完成后,运行效果如下所示:

首次安装

  • 接下来我们修改一下我们的程序,给窗体添加一个"确定"按钮,并再次"发布",此时我们可以看到我们早先设置的发布路径"D:\ClickOncePublish"子目录"Application Files"下多了一份程序,每次发布,新版本都会在此目录下进行保存,因此要小心文件夹占用空间过大。如下所示:

二次生成之后

  • 用户在打开我们程序的时候就会提示更新,他可以选择"跳过"(不建议,跳过后想更新只能重新安装或者等下一次新发布),那么他用的还是旧程序,如果选择"确定",则会下载新的程序:

ClickOnce更新提示

  • "确定"之后用户更新了他的程序,如下所示:

成功更新

  • 与Windows Installer安装的程序不同的是,我们在卸载ClickOnce程序的时候,会提示是否要回滚前一个版本,如下所示:

卸载ClickOnce安装的程序

  • 经测试,仅能回滚到前一个版本,不能无限回滚,之后只能选择移除程序。

证书制作

细心的同学可能会发现,当我们发布程序的时候,项目文件里多了一个"ClickOnceDemo_TemporaryKey.pfx"文件,这个是系统自动给我们生成的签名文件,你可以在"项目属性->签名"里看到,它只有一年的有效期:

如果你还有印象的话,我们上面在安装的时候,实际上系统仍然认为我们是"未知的发行者"而提出警告,因为这个证书是我们自己颁给自己的,操作系统认为这不行:

程序实体安装

因此,我们需要一份能够设定日期的并且能让系统认证通过的证书。

1、先找到你的VS命令行工具

通常在"开始菜单->Visual Studio"下应该能看到,譬如我装的VS2019,我的是"Developer Command Prompt for VS 2019"。如果你找不到,请参考Visual Studio 开发人员命令提示和开发人员 PowerShell

我们首先执行下面的命令:

makecert –r –n "CN=Zenronphy" –b 05/08/2021 –e 05/08/2026 –sv my.pvk my.cer

以上参数的意思是:

  • -r:创建自签署证书。
  • -n:指定主题的证书名称,你可以填写所有的信息,如"CN=公司名称, E=E-MAIL地址, O=组织名称, OU=组织单位, C=国家, S=省份(州), P=县城"。
  • -b:起效时间,格式为MM/dd/yy。
  • -e:失效时间,格式为MM/dd/yy。
  • -sv:生成.pvk 私钥文件。如果该文件不存在,系统将创建一个。

执行指令,将会弹出下面的创建密码窗口,请记住这个密码,后面我们会用上,当然你也可以选择None留空。这里我们简单的设置为:123456。

创建私钥密码

如果你选择了创建密码,接下来会弹出密码输入窗口,这个是用刚才创建的密码来创建证书,输错了就得重来一遍。

创建成功后,你就得到了my.pvk和my.cer两个文件。

2、将cer文件转换成spc文件

同样在VS命令行工具里执行:

cert2spc my.cer my.spc

这样你就得到了一个my.spc文件,spc是Software Publisher Certificate的意思。

3、将pvk文件和spc文件合成vs能识别的pfx文件

在VS命令行工具里输入:

pvk2pfx -pvk my.pvk -spc my.spc -pfx my.pfx -pi 123456789 –po 123456789
  • pvk:指定刚才生成的.pvk文件。
  • spc:就是刚才生成的.spc文件。
  • pfx:要生成的.pfx文件的名字。
  • pi:.pvk文件的密码,即我们前面创建的123456。
  • po:生成的.pfx文件的密码,你可以重新设,我这里还是用123456,后面在VS导入时会用到这个密码。

我们也可以使用pvkimprt工具(下载,提取码:m5ut ),执行以下命令:

pvkimprt -pfx my.spc my.pvk

会弹出一个密码输入框,输入上面创建私钥时的密码即可进入向导程序,中间需要注意的是这里,你需要选"是,导出私钥":

生成pfx文件向导注意事项

跟着向导指示,完成之后,你就得到了pfx文件。

4、将pfx导入项目签名

回到VS,打开项目属性窗口,选择签名,选择"从文件选择",选择我们上面生成的pfx文件。

导入pfx文件

客户端安装证书

打开"控制面板",搜索"证书",找到"管理计算机证书"。你也可以直接在CMD里输入"certmgr.msc",打开管理界面,如下图所示:

证书管理界面

将上面创建的cer文件发到客户端,在"受信任的根证书颁发机构"和下面的"受信任的发布者"中都"右键选择所有任务->导入",根据向导导入我们的证书文件。

这样之后客户安装、更新、卸载我们的程序,就再也不会跳出"应用程序安装 - 安全警告"了,真正实现ClickOnce,并且我们可以根据我们的实际需要设定证书日期,不会因为一年过期就出现各种不可预知的问题。

参考资料

1、ClickOnce发布时报错:Cannot publish because a project failed to build

2、Makecert工具使用参数说明

3、你了解HTTPS,但你可能不了解X.509

4、在决定使用ClickOnce发布你的软件前,应该知道的一些事情

5、ClickOnce部署Winform程序的方方面面

6、启用"从与我的应用程序相同的位置下载系统必备组件"

posted @ 2023-12-20 19:11  NPC老郑  阅读(218)  评论(0编辑  收藏  举报