记初步使用 Installer Projects (VS 2017 Community) 制作安装包的流程

写在前面:

  1. 我目前的学术研究方向比较传统,与 IT 关联不大(甚至难以学科交叉),在该领域纯属外行,文章在形式和内容上不期望与业内人士比肩。
  2. 我对计算机略有涉猎,偶尔做点东西娱乐自己,每当遇到一些值得整理的问题就顺手记录下来,没有广大程序猿和 IT 工作者那样的高尚情操,不是以能帮助到别人为初衷(若有幸当然更好),只是单纯地为了让自己的下次更顺利。所以在内容和形式上主要以服务我自己优先,望读者不喜勿喷。

1 环境

软件环境:VS 2017 Community (安装 Unity 时自带的,已装 C#)
系统环境:Win10 1909 x64

2 安装 Installer Projects 扩展

添加方法:

  1. 打开vs,在菜单中点 工具 - 扩展和更新
  2. 在打开的窗口左侧点 联机,然后在右上角输入“Installer Projects”,等搜索完毕后即可出现“Microsoft Visual Studio Installer Projects”,创建者是 Microsoft。选中它,点下载
  3. 下载完毕后,提示需要关闭所有vs窗口才能安装。按要求关闭以后在弹出窗口(VSIX Installer)内点“修改”,等安装完成再次打开vs即可。

注:当时遇到 VSIX Installer 安装失败的问题。重启电脑自行解决。
图2-1 安装扩展图2-2 安装扩展图2-3 安装扩展时你会遇到类似的窗口

3 创建工程

创建方法:

  1. 在菜单里:点 文件 - 新建
  2. 在“新建项目”窗口内,依次点 其他项目类型 - Visual Studio Installer;然后选第一个 Setup Project,确定好项目名称和保存位置后,最后点确定
    图3-1 创建工程

4 设置工程

1 界面说明

  • 左侧:目标计算机(安装包将要被安装到此机器)。左侧相当于安装包安装后对目标计算机作出的修改,其修改效果的视图。只会显示文件夹的层次结构。

    图4-1 界面左侧

  • 右侧:显示左侧选定的某个文件夹内的待安装文件。此时是空的,稍后将文件放入即可。
    图4-2 界面右侧

2 特殊文件夹

左侧,默认只有下列3个文件夹,其功能如下:
图4-3 默认的文件夹

文件夹 描述 Property
Application Folder 安装包内文件在目标计算机中的安装位置 TARGETDIR
User’s Desktop 目标计算机的桌面 DesktopFolder
User’s Programs Menu 目标计算机的程序文件夹。(不过在我的机器上就等同于开始菜单根目录,点徽标键就能看见的那个,这正常吗?) ProgramMenuFolder

稍后只需将待安装文件放到这些文件夹内即可,而无需考虑这些文件夹在不同目标计算机内的实际路径不同的问题,安装程序会自动确定。

在工程内使用 [ 特殊文件夹的 Property 属性的值 ] (含括号)来代指这些特殊文件夹的真实路径。如:"[TARGETDIR]test.exe"。

关于 Application Folder,其相较其他特殊文件夹多一 DefaultLocation 属性,默认值为 [ProgramFilesFolder][Manufacturer]\[ProductName],代表默认安装路径(其中[ProgramFilesFolder] 代表 “C:\Program Files\” 或 “C:\Program Files (x86)\”,取决于此项目的 TargetPlatform 属性的值,但一定以"\"结尾;[Manufacturer] 和 [ProductName] 是项目的 Manufacturer 和 ProductName 属性的值,见后文)。

如果需要其他的特殊文件夹,可以右键 - Add Special Folder,添加所的特殊文件夹。其 Property 可先在左侧选中文件夹,然后在属性窗口中查看到。
图4-4 添加特殊文件夹

3 项目的属性

注意:直接在解决方案资源管理器窗口中对项目点左键,在属性窗口中就会出现项目的属性。而不是对项目点右键,再点(工程的)属性。
图4-5 项目的属性
必须修改的属性:

属性 描述 我的操作
Manufacturer 制造商,影响到安装路径
ProductName 产品名称,影响到安装路径
RemovePreviousVersions 安装前如果检测到旧版本是否先移除 必须改为 True,否则会造成新老版本重叠
TargetPlatform 安装程序适用平台,影响到安装路径和所有待安装的 Assembly(部分 *.exe; *.dll 等) 按需要改为 x86 或 x64(Itanium 选项是什么?)
Version 版本 务必认真对待,影响到程序的更新和升级;改完后建议生成新的 ProductCode 选是选否都可

建议修改的属性:

属性 描述 我的操作
AddRemoveProgramsIcon 安装后的程序在目标计算机的控制面板 - 程序和功能 中显示的图标 稍后将它指向图标文件,现在由于没有添加图标文件,还不能操作
Author 作者名
Description 安装包描述
Title 标题,在文件资源管理器里把鼠标悬停到文件上会显示

其他的属性看情况修改。

4 配置安装前所需组件

解决方案资源管理器窗口中对项目点右键,再点属性。在弹出的属性页中点 Prerequisites,在弹出的系统必备窗口中勾选安装包需要的组件。
图4-6 工程的属性图4-7 属性页图4-8 系统必备
如果没有,建议把系统必备窗口中的“创建用于安装系统必备组件的安装程序勾掉,这影响到生成后的文件,稍后将提到。我这里把它勾掉了。
图4-9 系统必备
关于“系统必备组件的安装位置” 和 “Installation URL” 的配置我没有过多尝试,如有需要请搜索其他资料,或日后探索。

5 尝试生成

尝试生成,发现可以生成成功。
图4-10 尝试生成
如果未勾选“创建用于安装系统必备组件的安装程序”则应当只有一个 .msi 的安装包;否则还有一个 setup.exe 文件(此时 .msi 也可单独运行,故猜测可能是用于安装系统必备组件的)。

5 添加待安装文件

1 需要准备的文件

  1. 待安装文件
    将待安装文件夹备好。如果此时所有的待安装文件在一个文件夹里,则其名称不是安装后的目标名称, ProductName 才是目标名称。
    需要确保安装文件内的所有Assembly(部分 .exe 和 .dll 等)都能够与 TargetPlatform 匹配。
  2. 图标文件
    接下来有多处用到图标的地方。图标可以来自 .ico 或 .exe 或 .dll。我用独立的 ico。
  3. msiexec.exe
    使用此文件创建卸载程序。
    此文件位于"C:\Windows\System32\msiexec.exe"。它需要与 TargetPlatform 匹配, 虽然叫 System32 但如果你的机器是64位,则该文件也是64位的;或者你在用64位机器制作32位安装包,则在你的电脑上的那个是不匹配的。总之确保匹配而且在目标计算机能正常运行,则可以直接复制一份待用;或者直接到这里下载也可(x64 和 x86 均包含):
    https://download.csdn.net/download/simoral/10429167

都准备好后大概是这样的:
图5-1 初步准备好

  1. 图标文件msiexec.exe 放到 待安装文件
    把它们都放一起,它们最后都会被安装。为了更有层次,可在待安装文件夹内新建一个文件夹,名字随意,将图标文件和 msiexec.exe 放进去。

最终效果如下:
图5-2 准备好
图5-3 准备好

2 添加到安装包

先在 文件资源管理器 里进到待安装文件夹,在此 全选 - 复制(不要在文件夹外复制),然后在vs界面左侧点击“Application Folder”,然后在vs界面 右侧右键 - 粘贴
图5-4 复制图5-5 粘贴
导入可能是一个漫长的过程,需要稍等。完成后效果大概这样:
图5-7 导入
可以发现,部分 .Net 编写的 .exe 和 .dll 等被认为是 Assembly,其他的被认为是 File。还有一部分 Assembly 被导入为与原文件同名的但扩展名大写者,与原文件同时存在;不用担心,实际安装时不会被输出。
图5-8 导入后导入后,别忘了之前的项目的属性的 AddRemoveProgramsIcon 尚未设定,此时已经可以设定了。

3 创建快捷方式

右侧,对要创建快捷方式的 exe 点 右键 - Create Shortcut to xxx.exe 即可。
图5-9 创建快捷方式选中产生的快捷方式,修改其属性:

属性 描述
(Name) 显示的名称
Arguments 该快捷方式的启动参数,没有可以空着
Description 鼠标悬停时显示的提示
Icon 图标

图5-10 快捷方式属性
改好后,在右侧拖动快捷方式,到左侧的某个文件夹上松开,快捷方式进去了,则安装包安装后将在那里创建快捷方式。一般是拖进 User’s Desktop 或 User’s Programs Menu,就能在目标计算机桌面或程序菜单创建快捷方式了,或者两个都要。如果快捷方式较多,为了整洁,也可以在 User’s Programs Menu 内创建个文件夹什么的。

(P.S. 我想知道怎么能让 CSDN Markdown 不要自动把单独的英文引号转换为中文引号?转义字符也不行。)
图5-11 移动快捷方式

4 创建卸载程序的快捷方式

原理:要操作一个具有 ProductCode 的程序的安装状态,本质上是运行 msiexec.exe 并传入参数(具体参数可手动运行它查看)。要卸载某个程序,只需要在 msiexec.exe 的快捷方式中传入参数为 /x {ProductCode}。

方法:创建 msiexec.exe 的快捷方式,修改属性,其中 Argument 属性改为:/x {ProductCode}。其中,{ProductCode} 可以在 项目的 ProductCode 属性 处获得,注意带着括号复制过来。
图5-12 ProductCode
图5-13 配置卸载程序定的快捷方式
完毕后,将卸载快捷方式拖入适当的目标文件夹。

6 高级操作(你可能不需要)

1 安装后写入注册表

在项目上点右键 - View - 注册表,即可打开目标计算机上的注册表。
图6-1 浏览注册表将目标注册表项键值插入,类似 Regedit,即可在安装后写入注册表。
图6-2 编辑注册表
这样做好处是不需要自己写代码操作注册表,那样需要获取管理员权限,还涉及不同机器位置不同的问题。但不确定在卸载时会不会卸载掉自定义的注册表,好像会,这里有待证实。

2 重写安装函数

参考:https://blog.csdn.net/smallbabylong/article/details/78756530

目标:重写原生的 BeforeInstall、AfterInstall、AfterRollback、AfterUninstall、BeforeRollback、BeforeUninstall 等函数以便能在相应的事件执行时执行我自己的代码。

方法文件 - 添加 - 新建项目 - 已安装 - 其他语言 - Visual C# - 类库(.NET Framework)(不要点成另一个),命名并选择路径和框架,点确定。
图6-3 插入类库(.Net Framework)
在类库的项目下,删除 Class1.cs,添加 - 新建项 - 安装程序类(不是别的类),重命名、添加后打开(可能需要在弹出的对话框内点一下切换到代码视图)。
图6-4 插入安装程序类
此安装程序类继承自 System.Configuration.Install.Installer。它里面默认只有一个构造函数。现在安装程序原本不能直接完成的功能,都可以在这个类里通过重写原生函数自己实现。复制下列代码加入构造函数之后,然后自行修改即可。

protected override void OnBeforeInstall(IDictionary savedState)
{
    // 这里需要 protected 而不能是 public
    //
    // 
    // Do your things here ...
    //
    base.OnBeforeInstall(savedState);
}

public override void Install(IDictionary stateSaver)
{
    // 
    // Do your things here ...
    //
    base.Install(stateSaver);
}

protected override void OnAfterInstall(IDictionary savedState)
{
    // 这里需要 protected 而不能是 public
    //
    // 
    // Do your things here ...
    //
    base.OnAfterInstall(savedState);
}

public override void Uninstall(IDictionary savedState)
{
    // 
    // Do your things here ...
    //
    base.Uninstall(savedState);
}

public override void Rollback(IDictionary savedState)
{
    // 
    // Do your things here ...
    //
    base.Rollback(savedState);
}

7 生成

1 生成成功

强烈建议生成前先打开输出窗口以便观察错误提示。点视图 - 其他窗口 - 输出
图7-1 打开输出窗口如果一切顺利,此时执行生成,即可生成成功。也可能会遇到一些问题。

2 可能遇到的问题

1 ERROR: … should be excluded because its source file … is under Windows System File Protection.

可能遇到的错误:
ERROR: ‘System.EnterpriseServices.tlb’ should be excluded because its source file ‘C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.EnterpriseServices.tlb’ is under Windows System File Protection.
图7-2 可能遇到的错误原因:某些(被自动解析出来的)“受保护的” Assembly 不能被放入包。
办法:将出错对象的 Exclude 属性设为 True,则可使其排除在包外。不用担心,这些组件往往是系统核心文件,出于安全考虑才被禁止入包,所以每个机器都有该文件。
图7-3 解决办法被排除的文件在右侧不显示, 但在解决方案管理器窗口的 Detected Dependencies 中,其左下角显示一小图标。
图7-4 解决办法

2 WARNING: Unable to find dependency …

可能遇到的警告(不会导致生成失败):
WARNING: Unable to find dependency ‘ICSHARPCODE.SHARPZIPLIB’ (Signature=‘1B03E6ACF1164F73’ Version=‘0.86.0.518’) of assembly ‘NPOI.OpenXml4Net.DLL’
图7-5 可能遇到的错误
原因:找不到依赖项。虽然该文件存在,但与要求的版本号(如图,0.86.0.518)不同也会触发。
办法:更换为正确的文件。

3 安装程序的实际运行

在文件资源管理器中查看,发现项目的 DescriptionTitle 属性似乎会合并到“标题”里面,介意可以改掉,在文件的属性里可直接编辑。
图7-6 实际文件图7-7 实际文件的属性
运行时大概这样子的:
图7-8 实际界面图7-9 实际界面
再运行就是安装了,然后就是完毕了;如果点取消会提示未完成;安装过程中取消会回滚操作。没有声明界面,整体流程比较简洁明了,如果有需要也可以自定义界面,在项目上点右键 - View - 用户界面。以后研究。

安装的程序可以在控制面板里管理,可以被软件管家之类的杀毒软件管理。如果已安装,再次运行安装包,会进入修复卸载页面。

8 一些疑惑

  1. 我查的所有资料发现都要添加主输出,然而我很难理解它的作用?而且我没有添加也能正常工作。

9 参考资料

  1. https://blog.csdn.net/dog123xuheyin/article/details/85008071
  2. https://blog.csdn.net/smallbabylong/article/details/78756530
  3. https://www.cnblogs.com/Leo_wl/p/11144773.html
发布了4 篇原创文章 · 获赞 0 · 访问量 188

猜你喜欢

转载自blog.csdn.net/xzqsr2011/article/details/103396447
今日推荐