[TOC]
# 安装
**打开VS2017:工具 --> 扩展和更新 --> 联机,搜索Microsoft Visual Studio 2017 Installer Projects**

重启安装下
# 新建项目
**安装好。打开VS2017,在需要安装的解决方下,开始新建安装项目,如下图:**
**【新建】-【项目】-【已安装】-【模板】-【其他项目类型】-【Visual studio Installer】**

选择`Visual Studio Installer --> 安装项目`,并填写项目名称和保存位置,点击“确定”按钮,项目就创建好了,如下图所示:

在`应用程序文件夹`处单击鼠标右键选择`添加 --> 文件夹`,如下图所示:

我们不妨将文件夹命名为 CDemo。这个文件夹就是程序安装后所在安装路径下生成的、包含程序相关组件的文件夹。例如,用户选择将程序安装到 D:\\Program Files\\ 目录,那么安装时会先在该目录创建一个名称为 CDemo 的新文件夹,再将程序的所有组件拷贝到 CDemo 中,最终程序的所有文件是在 D:\\Program Files\\CDemo\\ 目录下。
接下来,向 CDemo 文件夹中添加程序要用到的所有文件,如下图所示:

添加好以后如下图所示

demo.exe 是我们编译好的可执行文件,demo.ico 和 uninstall.ico 是图标,用来创建快捷方式。程序图标必须是`.ico`格式,可以通过 jpg、png 等常见图片格式在线转换。文章最后会给出两个图标的下载地址。
> 制作安装包之前,可以将程序使用到的所有文件都拷贝到一个目录下,这样就可以一次性添加到 CDemo。
**实现卸载功能**
如果要实现卸载功能的话,还需要将`C:\Windows\System32\msiexec.exe`也添加到 CDemo 中。
**添加快捷方式**
快捷方式存在于两个地方,分别是桌面和开始菜单,`用户的“程序”菜单`用来存放开始菜单中的快捷方式,`用户桌面`用来存放桌面上的快捷方式。
在"demo.exe"上单击鼠标右键选择`创建demo.exe的快捷方式`,如下图所示

用鼠标单击生成的快捷方式,在右侧会弹出属性面板,如下图所示:

Name 表示快捷方式的名称,一般是程序名;Description 表示对快捷方式的说明,也就是鼠标悬浮时显示的文本;Target 表示快捷方式指向哪个可执行程序;Icon 表示图标,可以按照下图所示的方式添加

按照同样的方式为 msiexec.exe 也生成快捷方式,并将 Name 设置为“卸载CDemo”,将 Description 设置为“卸载CDemo程序”,将 Icon 设置为“uninstall.ico”。
在`用户的“程序”菜单`下新建文件夹 CDemo,将两个快捷方式剪切粘贴到该文件夹下。然后再为 demo.exe 创建快捷方式,并剪切粘贴到`用户桌面`下。
这样,程序安装后在桌面和开始菜单中都有快捷方式,都可以启动了。
**实现卸载功能**
上面我们虽然添加了系统自带的卸载程序,并为卸载程序创建了快捷方式,但目前依然无法实现卸载功能,因为还不知道要卸载哪个程序。
在项目名称`CDemoSetup`上单击鼠标右键,会看到右侧出现一个属性面板,如下图所示

ProductCode 是产品代码,即产品ID,我们需要将它告诉卸载程序。每个程序的ID都不同,有了它,卸载程序才知道卸载哪一个软件。本例中,程序ID为`{F61A9A34-29C4-45D2-9555-1D4E1D256FDF}`。
在卸载程序 msiexec.exe 的快捷方式上单击鼠标右键,在右侧属性面板中,将 Arguments 的值设置为`/x{F61A9A34-29C4-45D2-9555-1D4E1D256FDF}`,如下图所示

这样,卸载程序就知道卸载哪个软件了。
**选择系统必备**
在项目名称 CDemoSetup 上点击鼠标右键,选择“属性”,弹出如下的对话框:

点击“系统必备”,弹出如下对话框:

可以在这里选择程序需要的系统组件。我们的程序不需要任何组件,所以将`创建用于安装系统必备组件的安装程序`前面的对勾取消,然后点击“确定”按钮,就设置完成了。
至此,我们的安装包就编辑完成了,生成项目后,可以在Debug目录下看到 CDemoSetup.msi 文件,这就是我们制作好的安装包,双击运行,就可以安装我们的程序了。
安装完成后,就可以在开始菜单和桌面上看到快捷方式了,如下图所示:

- c语言
- 基础知识
- 变量和常量
- 宏定义和预处理
- 随机数
- register变量
- errno全局变量
- 静态变量
- 类型
- 数组
- 类型转换
- vs中c4996错误
- 数据类型和长度
- 二进制数,八进制数和十六进制数
- 位域
- typedef定义类型
- 函数和编译
- 函数调用惯例
- 函数进栈和出栈
- 函数
- 编译
- sizeof
- main函数接收参数
- 宏函数
- 目标文件和可执行文件有什么
- 强符号和弱符号
- 什么是链接
- 符号
- 强引用和弱引用
- 字符串处理函数
- sscanf
- 查找子字符串
- 字符串指针
- qt
- MFC
- 指针
- 简介
- 指针详解
- 案例
- 指针数组
- 偏移量
- 间接赋值
- 易错点
- 二级指针
- 结构体指针
- 字节对齐
- 函数指针
- 指针例子
- main接收用户输入
- 内存布局
- 内存分区
- 空间开辟和释放
- 堆空间操作字符串
- 内存处理函数
- 内存分页
- 内存模型
- 栈
- 栈溢出攻击
- 内存泄露
- 大小端存储法
- 寄存器
- 结构体
- 共用体
- 枚举
- 文件操作
- 文件到底是什么
- 文件打开和关闭
- 文件的顺序读写
- 文件的随机读写
- 文件复制
- FILE和缓冲区
- 文件大小
- 插入,删除,更改文件内容
- typeid
- 内部链接和外部链接
- 动态库
- 调试器
- 调试的概念
- vs调试
- 多文件编程
- extern关键字
- 头文件规范
- 标准库以及标准头文件
- 头文件只包含一次
- static
- 多线程
- 简介
- 创建线程threads.h
- 创建线程pthread
- gdb
- 简介
- mac使用gdb
- setjump和longjump
- 零拷贝
- gc
- 调试器原理
- c++
- c++简介
- c++对c的扩展
- ::作用域运算符
- 名字控制
- cpp对c的增强
- const
- 变量定义数组
- 尽量以const替换#define
- 引用
- 内联函数
- 函数默认参数
- 函数占位参数
- 函数重载
- extern "C"
- 类和对象
- 类封装
- 构造和析构
- 深浅拷贝
- explicit关键字
- 动态对象创建
- 静态成员
- 对象模型
- this
- 友元
- 单例
- 继承
- 多态
- 运算符重载
- 赋值重载
- 指针运算符(*,->)重载
- 前置和后置++
- 左移<<运算符重载
- 函数调用符重载
- 总结
- bool重载
- 模板
- 简介
- 普通函数和模板函数调用
- 模板的局限性
- 类模板
- 复数的模板类
- 类模板作为参数
- 类模板继承
- 类模板类内和类外实现
- 类模板和友元函数
- 类模板实现数组
- 类型转换
- 异常
- 异常基本语法
- 异常的接口声明
- 异常的栈解旋
- 异常的多态
- 标准异常库
- 自定义异常
- io
- 流的概念和类库结构
- 标准io流
- 标准输入流
- 标准输出流
- 文件读写
- STL
- 简介
- string容器
- vector容器
- deque容器
- stack容器
- queue容器
- list容器
- set/multiset容器
- map/multimap容器
- pair对组
- 深浅拷贝问题
- 使用时机
- 常用算法
- 函数对象
- 谓词
- 内建函数对象
- 函数对象适配器
- 空间适配器
- 常用遍历算法
- 查找算法
- 排序算法
- 拷贝和替换算法
- 算术生成算法
- 集合算法
- gcc
- GDB
- makefile
- visualstudio
- VisualAssistX
- 各种插件
- utf8编码
- 制作安装项目
- 编译模式
- 内存对齐
- 快捷键
- 自动补全
- 查看c++类内存布局
- FFmpeg
- ffmpeg架构
- 命令的基本格式
- 分解与复用
- 处理原始数据
- 录屏和音
- 滤镜
- 水印
- 音视频的拼接与裁剪
- 视频图片转换
- 直播
- ffplay
- 常见问题
- 多媒体文件处理
- ffmpeg代码结构
- 日志系统
- 处理流数据
- linux
- 系统调用
- 常用IO函数
- 文件操作函数
- 文件描述符复制
- 目录相关操作
- 时间相关函数
- 进程
- valgrind
- 进程通信
- 信号
- 信号产生函数
- 信号集
- 信号捕捉
- SIGCHLD信号
- 不可重入函数和可重入函数
- 进程组
- 会话
- 守护进程
- 线程
- 线程属性
- 互斥锁
- 读写锁
- 条件变量
- 信号量
- 网络
- 分层模型
- 协议格式
- TCP协议
- socket
- socket概念
- 网络字节序
- ip地址转换函数
- sockaddr数据结构
- 网络套接字函数
- socket模型创建流程图
- socket函数
- bind函数
- listen函数
- accept函数
- connect函数
- C/S模型-TCP
- 出错处理封装函数
- 多进程并发服务器
- 多线程并发服务器
- 多路I/O复用服务器
- select
- poll
- epoll
- epoll事件
- epoll例子
- epoll反应堆思想
- udp
- socket IPC(本地套接字domain)
- 其他常用函数
- libevent
- libevent简介