最近公司在赶一个项目,打包完成的安装包安装完成后会有一个报错,如下图:

复现问题

出现该问题的详细环境如下(也就是一个复现问题的步骤):

  • 开启了 Windows 兼容性助手的服务 Program Compatibility Assistant Service
  • 使用 IE 浏览器下载直接运行的程序(可能与 IE 的 SmartScreen 筛选器有关)
  • 安装程序带有 setup 关键字

用以上环境下载并安装程序后,就会有上面的提示。

解决思路

搜索了相关资料,有几个关联的资料分别记录在这里:

解决步骤

通过上面的几个资料我分别查询了一下 .manifest 文件的作用,以及如何在 Visual Studio 中生成和使用 .manifest 文件。资料如下:

首先通过 Visual Studio 打开你的项目属性,连接器->清单文件,将 生成清单 设置为是: 然后打开 清单工具->输入和输入和输出,将 嵌入清单 改为 ,此时下面的输出清单文件会自动填充一个路径,程序编译后就会在这个路径下生成一个以应用程序名字命名的清单文件。如下图: 修改完成保存后,编译一下程序(注意别编译错了版本,我修改了 release 版本的去编译 debug 版本的,搞了半天也没生成,实际是生成错了)。编译完成后,在 exe 生成的目录下就会出现一个以 .manifest 后缀结尾的文件,用记事本打开默认的文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"></requestedExecutionLevel>
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="x86" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity>
</dependentAssembly>
</dependency>
</assembly>

根据 Targeting your application for Windows 的介绍,我们增加一些支持的系统版本,修改完成后如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"></requestedExecutionLevel>
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="x86" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity>
</dependentAssembly>
</dependency>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
</application>
</compatibility>
</assembly>

此时清单文件我们准备好了,需要把这个清单文件嵌入到应用程序中,此时再次打开 清单工具->输入和输入和输出,将 嵌入清单 改为 ,这时 输出清单文件 会被清空,我们在上面的 附加清单文件 中添加我们刚才生成好的清单文件,用宏路径可以这样写 $(TargetPath).manifest,如下图: 添加完成后,再次编译程序,清单文件就会嵌入到程序中了,此时我们再将程序部署到线上环境提供下载后,就不会出现文章开头说明的问题了。