Wix 每个用户安装程序以检测 Visual C++ 2015 Redistributable [英] Wix per user installer to detect the Visual C++ 2015 Redistributable
问题描述
我正在创建一个 .msi 安装程序,它必须确定系统中是否存在 Visual C++ 2015 Redistributable,如果没有,则使用自定义消息中断安装.官方 Wix 文档指的是 VC++ 的实际安装,我不希望这样做,因为我的安装程序是每个用户",还有其他几个 stackoverflow 问题指的是捆绑包而不是 .msi http://wixtoolset.org/documentation/manual/v3/howtos/redistributables_and_install_checks/install_vcredist.html.
Wix Burn vcredist, WIX 检查是否安装了 VS2015 C++ 可再发行组件 , https://gist.github.com/nathancorvussolis/6852ba282647aeb0c5c00e742e28eb48
所以我想问题是,如何有效地检测每个用户安装程序中是否存在 Visual C++ 2015 Redistributable.
运行时检测方法
我可以找到几种方法来检测 Visual C++ 运行时的存在.
注册表
- VCRedist 安装程序使用的密钥(见下文)
- 中提到的键我的原始答案 - 从这个旧答案中获取
文件存在与版本检查
- 检查是否存在核心运行时文件
- 请参阅下面的单独部分
MSI API
- 您可以通过查找产品 GUID 来检测是否安装了特定的 MSI
- 可靠,但难以跟踪所有产品 GUID(不同版本)
- 更新:您还可以使用如下所述的升级代码.它应该在发布和更新之间保持稳定(对于每个主要版本,也可能在主要版本之间).
Fall-Over EXE?
- 建议使用 EXE,具体取决于运行时
- 启动它并失败意味着运行时不存在或损坏
好&不好 - 评估:选项 1
似乎容易受到攻击,因为部署运行时的合并模块变体可能不会写入这些密钥.选项 3
可能效果很好,但很难跟踪所有 GUID.Option 4
似乎已经失败,因为较新的运行时删除了某些注册表项.虽然现在已经修复,但它可能会重新出现.
文件版本存在/版本检查
我看的越多,我越开始认为您必须检查实际文件本身,并可能检查正确的文件版本.System32
文件夹(64 位版本)和 中的文件
文件夹(32 位版本)?查看文件列表在这里底部.vcruntime140.dll
SysWOW64
只是添加一个安全保存的链接.
测试 VBScript - 仅用于测试目的(脚本有时会被防病毒软件阻止):
设置 fso = CreateObject("Scripting.FileSystemObject")MsgBox fso.GetFileVersion("C:WindowsSystem32vcruntime140.dll")
您可以在 MSI 文件中使用 AppSearch 检测文件的存在和版本.
下面是我写的一些其他的东西,只是把它留在里面.
VCredist
似乎是 Visual C++ Redistributable Packages(VCRedist_x86.exe
、VCRedist_x64.exe
) - 这是部署运行时的推荐方法 - 检查以下注册表项以确定实际安装的运行时版本:
HKLMSOFTWAREMicrosoftVisualStudio<版本>VCRuntimes
子键 x86 和 x64 似乎都包含一个Installed";安装运行时时设置为 1 的值.我会假设 - 没有时间测试它 - 然后你可以检查:
HKLMSOFTWAREWOW6432NodeMicrosoftVisualStudio14.0VCRuntimesx64
Installed = 1
HKLMSOFTWAREWOW6432NodeMicrosoftVisualStudio14.0VCRuntimesx86
Installed = 1
合并模块:经过简单检查,这些值似乎不是由也可用于分发此运行时的合并模块写入的.我现在没有时间或方法来正确检查.
令人惊讶的是,2015 版和 2017 版运行时都写入了 14.0 密钥 - 因为它们是二进制兼容的. 如果安装了 2017 版,则 VCRedist 可执行文件将返回错误,因为不需要安装.确实很奇怪.但为了您的目的,这应该是无关紧要的.来源.
MSI API - 检索产品代码
- Mailbag:如何检测VC 8.0运行时可再发行包的存在
- 更新的 VC 8.0 运行时可再发行包包含在 Visual Studio 2005 SP1 中
- 如何我可以找到已安装 MSI 设置的产品 GUID 吗?
<块引用>
更新:installer.ProductState
- 正常安装状态是5
:
我忘记了 ProductState 属性 写下面的时候.您可以使用两行代码检查已安装的产品,如果您有实际的产品代码:
Dim 安装程序:Set installer = CreateObject("WindowsInstaller.Installer")MsgBox installer.ProductState("{00000000-0000-0000-0000-000000000001}")
这里还有另一种方法:MSDN:如何以编程方式检查是否存在 Windows Installer基于产品的产品代码.
<块引用>提示:我不会使用这种方法,因为产品更新时产品代码会频繁更改.因此我更喜欢检查核心运行时文件的文件版本.这似乎更未来可靠(前提是版本解析正确完成并且可靠——不要自己动手).
样机:
公共安装程序设置安装程序 = CreateObject("WindowsInstaller.Installer")' 没有 2015 GUIDVC2015 = CheckForProductCode("{00000000-0000-0000-0000-000000000000}")VC2017 = CheckForProductCode("{C77195A4-CEB8-38EE-BDD6-C46CB459EF6E}")MsgBox "VC2015:"&CStr(VC2015) &vbCrLf &VC2017:"&CStr(VC2017)函数 CheckForProductCode(productcode)CheckForProductCode = False对于 installer.ProductsEx("", "", 7) 中的每个产品如果(LCase(productcode) = LCase(product.ProductCode)) 那么CheckForProductCode = True退出万一下一个结束功能
更新基于 Zett42 的建议列举共享相同升级代码的产品:
Set installer = CreateObject("WindowsInstaller.Installer")' 枚举与Microsoft Visual C++ 2008 Redistributable - x86 9.0.30729.4148"相关的所有产品' {AA783A14-A7A3-3D33-95F0-9A351D530011} 是升级代码设置升级 = installer.RelatedProducts("{AA783A14-A7A3-3D33-95F0-9A351D530011}")对于每个 u In 升级MsgBox u, vbOKOnly, 产品代码:"下一个
部署 Visual Studio C++ 运行时
除了检测之外,还有多种分发 Visual Studio C++ 运行时的方法:
- 静态链接
- Visual C++ 可再发行包
VCRedist_x86.exe
、VCRedist_x64.exe
或VCRedist_arm.exe
Program Files(x86)Microsoft Visual Studio2017editionVCRedistMSVClib-version
- 可再发行的合并模块(
.msm 文件
)- 不足以满足某些用途(通用 CRT):
- 本地应用程序文件夹
- 将 DLL 复制到本地应用程序文件夹
- 出于维修原因(更新、安全修复),不推荐使用
安全保存链接:
- 可再发行组件用于在 Windows 7 上部署使用 Visual Studio 2015 开发的 C++ exe
- 如何检测是否需要安装VCRedist?
- WIX 合并 c++ 运行时
- 如何检测 Visual C++ 2017 Redistributable 是否为已安装
旧答案
有这个旧帖子.我不太喜欢直接读取注册表,让我看看是否能找到更可靠的方法,但也许同时看看:检测是否安装了 Visual C++ Redistributable for Visual Studio 2012
还有一个链接,如何找到已安装产品的 Windows Installer 产品代码:如何找到已安装 MSI 设置的产品 GUID?
I am creating an .msi installer which has to determine whether the Visual C++ 2015 Redistributable is present in the system and if not then interrupt the installation with custom message. The official Wix documentation refers to the actual installation of the VC++ which I do not wish to do as my installer is "per user" , There are couple of others stackoverflow questions which refer to the bundle rather than the .msi http://wixtoolset.org/documentation/manual/v3/howtos/redistributables_and_install_checks/install_vcredist.html.
Wix Burn vcredist, WIX check if VS2015 C++ redistributable is installed , https://gist.github.com/nathancorvussolis/6852ba282647aeb0c5c00e742e28eb48
So I guess the question is, how to efficiently detect the presense of Visual C++ 2015 Redistributable in the per user installer.
Runtime Detection Approaches
I can find a few ways to detect the presence of the Visual C++ Runtime.
Registry
- Keys used by the VCRedist installer (see section below)
- Keys mentioned in my original answer - grabbed from this old answer
File Presence & Version Check
- Check for presence of core runtime files
- See separate section below
MSI API
- You can detect whether a specific MSI is installed by looking up the product GUID
- Reliable, but hard to keep track of all product GUIDs (different versions)
- UPDATE: You can also use the upgrade code as described below. It should remain stable across releases and updates (for each major version and potentially between major versions as well).
Fall-Over EXE?
- Suggestions are seen to use an EXE depending on the runtime
- Launching it and failing means the runtime is not there or broken
Good & Bad - Evaluation: Option 1
seems to be vulnerable since the merge module variant of deploying the runtime might not write these keys. Option 3
might work well, but it is hard to keep track of all GUIDs. Option 4
seems to already have failed based on the newer runtimes removing certain registry keys. Though fixed now, this could resurface.
File Version Presence / Version Check
The more I look at this, the more I start to think that you have to check for the actual files themselves, and potentially for the right file version. The file vcruntime140.dll
in the System32
folder (64-bit version) and SysWOW64
folder (32-bit version)? See files list towards bottom here.
Just adding a link for safe-keeping.
- How to detect the presence of the Visual C++ 2012 redistributable package?
- Redistributing Visual C++ Files
A test VBScript - for test purposes only (scripts are sometimes blocked by anti-virus):
Set fso = CreateObject("Scripting.FileSystemObject")
MsgBox fso.GetFileVersion("C:WindowsSystem32vcruntime140.dll")
You can detect file presence and version using AppSearch in an MSI file.
Below are some other stuff I wrote up, just leaving it in.
VCRedist
It seems the Visual C++ Redistributable Packages (VCRedist_x86.exe
, VCRedist_x64.exe
) - which is the recommende way to deploy the runtime - checks the following registry key to determine what versions of the runtime is actually installed:
HKLMSOFTWAREMicrosoftVisualStudio<version>VCRuntimes
The sub-keys x86 and x64 seem to all contain an "Installed" value that is set to 1 when the runtime is installed. I would assume - without having had time to test it all - that you then can check:
HKLMSOFTWAREWOW6432NodeMicrosoftVisualStudio14.0VCRuntimesx64
Installed = 1
HKLMSOFTWAREWOW6432NodeMicrosoftVisualStudio14.0VCRuntimesx86
Installed = 1
Merge Module: After a brief check, it looks like these values are not written by the merge modules that can also be used to distribute this runtime. I do not have the time or means to check this properly now.
Astonishingly both version 2015 and version 2017 of the runtime write to the 14.0 key - since they are binary compatible. If the 2017 version is installed, then the VCRedist executable will return an error since no install is needed. Weird indeed. But for your purpose that should be besides the point. Source.
MSI API - Retrieve Product Codes
- Mailbag: How to detect the presence of the VC 8.0 runtime redistributable package
- Updated VC 8.0 runtime redistributable packages are included in Visual Studio 2005 SP1
- How can I find the product GUID of an installed MSI setup?
UPDATE:
installer.ProductState
- normal installed state is5
:I forgot about the ProductState property when writing the below. You can check for an installed product with two lines of code if you have the actual product code:
Dim installer : Set installer = CreateObject("WindowsInstaller.Installer") MsgBox installer.ProductState("{00000000-0000-0000-0000-000000000001}")
Here is even one more way to do it: MSDN: How to programmatically check for the presence of a Windows Installer-based product by using its product code.
Tip: I wouldn't use this approach seeing as the product code changes frequently when products are updated. Hence I like better to check for file versions of core-runtime files. This seems more reliable for the future (provided version parsing is done correctly and reliably - don't roll your own).
Mockup:
Public installer
Set installer = CreateObject("WindowsInstaller.Installer")
' Don't have the 2015 GUID
VC2015 = CheckForProductCode("{00000000-0000-0000-0000-000000000000}")
VC2017 = CheckForProductCode("{C77195A4-CEB8-38EE-BDD6-C46CB459EF6E}")
MsgBox "VC2015: " & CStr(VC2015) & vbCrLf & "VC2017: " & CStr(VC2017)
Function CheckForProductCode(productcode)
CheckForProductCode = False
For Each product In installer.ProductsEx("", "", 7)
If(LCase(productcode) = LCase(product.ProductCode)) Then
CheckForProductCode = True
Exit For
End If
Next
End Function
Update based on Zett42's suggestion to enumerate products sharing the same upgrade code:
Set installer = CreateObject("WindowsInstaller.Installer")
' Enumerate all products related to "Microsoft Visual C++ 2008 Redistributable - x86 9.0.30729.4148"
' {AA783A14-A7A3-3D33-95F0-9A351D530011} is the upgrade code
Set upgrades = installer.RelatedProducts("{AA783A14-A7A3-3D33-95F0-9A351D530011}")
For Each u In upgrades
MsgBox u, vbOKOnly, "Product Code: "
Next
Deploying The Visual Studio C++ Runtime
Beyond detection, there are several approaches for distributing the Visual Studio C++ Runtime:
- Static Linking
- Visual C++ Redistributable Packages
VCRedist_x86.exe
,VCRedist_x64.exe
, orVCRedist_arm.exe
Program Files(x86)Microsoft Visual Studio2017editionVCRedistMSVClib-version
- Redistributable Merge Modules (
.msm files
)- Insufficient for some purposes (The universal CRT):
- Local Application Folder
- Copy DLLs to the local application folder
- Not recommended for servicing reasons (updates, security fixes)
Links For Safe Keeping:
- Redistributables for deploying C++ exe developed with Visual Studio 2015 on Windows 7
- How to detect whether I need to install VCRedist?
- WIX merge c++ runtime
- How to detect if Visual C++ 2017 Redistributable is installed
Old Answer
There is this old post. I am not too fond of direct registry reads, let me see if I can find a more reliable way, but maybe have a look in the mean time: Detect if Visual C++ Redistributable for Visual Studio 2012 is installed
Just one more link, how to find the Windows Installer product code of products that are installed: How can I find the product GUID of an installed MSI setup?
这篇关于Wix 每个用户安装程序以检测 Visual C++ 2015 Redistributable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!