从 visual studio .net 到 visual studio 2013,每个主版本的 c++++ 编译器和工具都包含一个新的独立版本的 microsoft c 运行时 (crt) 库。这些独立的 crt 版本在不同程度上彼此不兼容。例如,visual studio 2012 使用的 crt 库是第 11 版,名为 msvcr110.dll,而 visual studio 2013 使用的 crt 库是第 12 版,名为 msvcr120.dll。然而,从 visual studio 2015 开始,情况发生了变化。visual studio 2015 及其后续版本都采用了一个通用的 crt。
通用 CRT (UCRT) 是 Microsoft Windows 操作系统的一部分。它包含在 Windows 10 和 Windows Server 2016 或更高版本中。对于仍在扩展支持中的早期操作系统版本,可以通过 Windows 更新获取 UCRT。尽管支持通用 CRT 的本地部署,但存在一些限制。
最新支持的 Visual C++ 下载地址如下:
32位下载地址:https://www.php.cn/link/800f569916f0f5c1e487a9b5e976bdc4
.NET Framework 下载地址如下:
https://www.php.cn/link/e92ae67e4af9da61bbb3690018fa4f1e
.NET Framework 4.5.2 离线安装包下载地址:https://www.php.cn/link/8d4af5c8b9b40206046d4f2c889eceed
将本地安装下载文件放置在打包的代码同级的
runtime目录下。
加载文件的代码如下:
[Files]
Source: ".\runtime\VC_redist.x86.exe"; DestDir: "{tmp}"; Check: NeedInstallVC运行时安装的代码如下:
[Run]
Filename: "{tmp}\VC_redist.x86.exe"; Parameters: /q; WorkingDir: {tmp}; Flags: skipifdoesntexist; StatusMsg: "Install Microsoft Visual C++ Runtime ..."; Check: NeedInstallVC检测是否需要安装的代码如下:
[Code]
var vcRuntimeMissing: Boolean;
function NeedInstallVC(): Boolean;
begin
Result := vcRuntimeMissing;
end;
function InitializeSetup(): Boolean;
begin
if RegValueExists(HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{7D75664A-6C04-424C-82A1-EE88913E5F16}', 'Version')
or RegValueExists(HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{01FAEC41-B3BC-44F4-B185-5E8475AEB855}', 'Version')
then
begin
vcRuntimeMissing := false;
end
else
begin
vcRuntimeMissing := true;
end;
result := true;
end;检测运行库是否已安装是通过注册表进行的。每个版本的运行库都有唯一的产品ID。解压
VC_redist.x86.exe后,找到名为
0的文件并用文本文档打开,搜索
ProductCode可以找到两个代码,一个是 Minimum Runtime,另一个是 Additional Runtime,如下所示:
RollbackLogPathVariable="WixBundleRollbackLog_vcRuntimeMinimum_x86" ProductCode="{7D75664A-6C04-424C-82A1-EE88913E5F16}"和
RollbackLogPathVariable="WixBundleRollbackLog_vcRuntimeAdditional_x86" ProductCode="{01FAEC41-B3BC-44F4-B185-5E8475AEB855}"我们使用的是
WixBundleRollbackLog_vcRuntimeAdditional_x86,在注册表中搜索对应的产品ID即可。
在线下载并检测 C++ 安装环境的代码如下:
[Code]
function InitializeSetup: Boolean;
var Path:string;
ResultCode: Integer;
begin
if RegValueExists(HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{01FAEC41-B3BC-44F4-B185-5E8475AEB855}', 'Version') then
begin
Result := true;
end
else
begin
if MsgBox('系统检测到您没有安装VC++环境,是否立刻下载并安装?', mbConfirmation, MB_YESNO) = idYes then
begin
Path := ExpandConstant('{pf}/Internet Explorer/iexplore.exe');
Exec(Path, 'https://www.php.cn/link/daaf13a1565b64dc3779f551de67b95e', '', SW_SHOWNORMAL, ewWaitUntilTerminated, ResultCode);
MsgBox('请安装好VC++环境后,再运行本安装包程序!',mbInformation,MB_OK);
Result := false;
end
else
begin
MsgBox('没有安装VC++环境,无法运行程序,本安装程序即将退出!',mbInformation,MB_OK);
Result := false;
end;
end;
end;要检测 .NET 环境,可以查看各版本和系统的关系,参考以下链接:
https://www.php.cn/link/b09d978ea462060c446ed6833f58735c
查看本机的 .NET 版本,可以输入
regedit.exe,然后导航到以下注册表路径:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\ HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\policy\
检测 .NET 环境的脚本如下:
[Code] // Indicates whether the specified version and service pack of the .NET Framework is installed.// version -- Specify one of these strings for the required .NET Framework version: // 'v1.1' .NET Framework 1.1 // 'v2.0' .NET Framework 2.0 // 'v3.0' .NET Framework 3.0 // 'v3.5' .NET Framework 3.5 // 'v4\Client' .NET Framework 4.0 Client Profile // 'v4\Full' .NET Framework 4.0 Full Installation // 'v4.5' .NET Framework 4.5 // 'v4.5.1' .NET Framework 4.5.1 // 'v4.5.2' .NET Framework 4.5.2 // 'v4.6' .NET Framework 4.6 // 'v4.6.1' .NET Framework 4.6.1 // 'v4.6.2' .NET Framework 4.6.2 // 'v4.7' .NET Framework 4.7 // 'v4.7.1' .NET Framework 4.7.1 // 'v4.7.2' .NET Framework 4.7.2 // 'v4.8' .NET Framework 4.8
// service -- Specify any non-negative integer for the required service pack level: // 0 No service packs required // 1, 2, etc. Service pack 1, 2, etc. required function IsDotNetDetected(version: string; service: cardinal): boolean; var key, versionKey: string; install, release, serviceCount, versionRelease: cardinal; success: boolean; begin versionKey := version; versionRelease := 0;
// .NET 1.1 and 2.0 embed release number in version key if version = 'v1.1' then begin versionKey := 'v1.1.4322'; end else if version = 'v2.0' then begin versionKey := 'v2.0.50727'; end // .NET 4.5 and newer install as update to .NET 4.0 Full else if Pos('v4.', version) = 1 then begin versionKey := 'v4\Full'; case version of 'v4.5': versionRelease := 378389; 'v4.5.1': versionRelease := 378675; // 378758 on Windows 8 and older 'v4.5.2': versionRelease := 379893; 'v4.6': versionRelease := 393295; // 393297 on Windows 8.1 and older 'v4.6.1': versionRelease := 394254; // 394271 on Windows 8.1 and older 'v4.6.2': versionRelease := 394802; // 394806 on Windows 8.1 and older 'v4.7': versionRelease := 460798; // Windows 10 'v4.7.1': versionRelease := 461308; // Windows 10 'v4.7.2': versionRelease := 461808; // Windows 10 'v4.8' : versionRelease := 528040; // Windows 10 end; end; // installation key group for all .NET versions key := 'SOFTWARE\Microsoft\NET Framework Setup\NDP\' + versionKey; // .NET 3.0 uses value InstallSuccess in subkey Setup if Pos('v3.0', version) = 1 then begin success := RegQueryDWordValue(HKLM, key + '\Setup', 'InstallSuccess', install); end else begin success := RegQueryDWordValue(HKLM, key, 'Install', install); end; // .NET 4.0 and newer use value Servicing instead of SP if Pos('v4', version) = 1 then begin success := success and RegQueryDWordValue(HKLM, key, 'Servicing', serviceCount); end else begin success := success and RegQueryDWordValue(HKLM, key, 'SP', serviceCount); end; // .NET 4.5 and newer use additional value Release if versionRelease > 0 then begin success := success and RegQueryDWordValue(HKLM, key, 'Release', release); success := success and (release >= versionRelease); end; result := success and (install = 1) and (serviceCount >= service);end;
function InitializeSetup: Boolean; var Path:string; ResultCode: Integer; begin if IsDotNetDetected('v4.5.2', 0) then begin Result := true; end else begin if MsgBox('系统检测到您没有安装.Net Framework4.5.2,是否立刻下载并安装?', mbConfirmation, MB_YESNO) = idYes then begin Path := ExpandConstant('{pf}/Internet Explorer/iexplore.exe'); Exec(Path, 'https://www.php.cn/link/493c4b304be1e32548b7ad5d5c22ef6b', '', SW_SHOWNORMAL, ewWaitUntilTerminated, ResultCode); MsgBox('请安装好.Net Framework环境后,再运行本安装包程序!',mbInformation,MB_OK); Result := false; end else begin MsgBox('没有安装.Net Framework环境,无法运行程序,本安装程序即将退出!',mbInformation,MB_OK); Result := false; end; end; end;
注意,许多文章中提到的注册表地址
RegKeyExists(HKLM, 'SOFTWARE/Microsoft/.NETFramework/policy/v2.0')只能获取到较为粗略的版本信息(如 v2.0/v4.0),不建议使用。更详细的版本信息应从HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\路径获取。
检测 C++ 和 .NET 环境的完整代码如下:
[Code] // Indicates whether the specified version and service pack of the .NET Framework is installed.// version -- Specify one of these strings for the required .NET Framework version: // 'v1.1' .NET Framework 1.1 // 'v2.0' .NET Framework 2.0 // 'v3.0' .NET Framework 3.0 // 'v3.5' .NET Framework 3.5 // 'v4\Client' .NET Framework 4.0 Client Profile // 'v4\Full' .NET Framework 4.0 Full Installation // 'v4.5' .NET Framework 4.5 // 'v4.5.1' .NET Framework 4.5.1 // 'v4.5.2' .NET Framework 4.5.2 // 'v4.6' .NET Framework 4.6 // 'v4.6.1' .NET Framework 4.6.1 // 'v4.6.2' .NET Framework 4.6.2 // 'v4.7' .NET Framework 4.7 // 'v4.7.1' .NET Framework 4.7.1 // 'v4.7.2' .NET Framework 4.7.2 // 'v4.8' .NET Framework 4.8
// service -- Specify any non-negative integer for the required service pack level: // 0 No service packs required // 1, 2, etc. Service pack 1, 2, etc. required function IsDotNetDetected(version: string; service: cardinal): boolean; var key, versionKey: string; install, release, serviceCount, versionRelease: cardinal; success: boolean; begin versionKey := version; versionRelease := 0;
// .NET 1.1 and 2.0 embed release number in version key if version = 'v1.1' then begin versionKey := 'v1.1.4322'; end else if version = 'v2.0' then begin versionKey := 'v2.0.50727'; end // .NET 4.5 and newer install as update to .NET 4.0 Full else if Pos('v4.', version) = 1 then begin versionKey := 'v4\Full'; case version of 'v4.5': versionRelease := 378389; 'v4.5.1': versionRelease := 378675; // 378758 on Windows 8 and older 'v4.5.2': versionRelease := 379893; 'v4.6': versionRelease := 393295; // 393297 on Windows 8.1 and older 'v4.6.1': versionRelease := 394254; // 394271 on Windows 8.1 and older 'v4.6.2': versionRelease := 394802; // 394806 on Windows 8.1 and older 'v4.7': versionRelease := 460798; // Windows 10 'v4.7.1': versionRelease := 461308; // Windows 10 'v4.7.2': versionRelease := 461808; // Windows 10 'v4.8' : versionRelease := 528040; // Windows 10 end; end; // installation key group for all .NET versions key := 'SOFTWARE\Microsoft\NET Framework Setup\NDP\' + versionKey; // .NET 3.0 uses value InstallSuccess in subkey Setup if Pos('v3.0', version) = 1 then begin success := RegQueryDWordValue(HKLM, key + '\Setup', 'InstallSuccess', install); end else begin success := RegQueryDWordValue(HKLM, key, 'Install', install); end; // .NET 4.0 and newer use value Servicing instead of SP if Pos('v4', version) = 1 then begin success := success and RegQueryDWordValue(HKLM, key, 'Servicing', serviceCount); end else begin success := success and RegQueryDWordValue(HKLM, key, 'SP', serviceCount); end; // .NET 4.5 and newer use additional value Release if versionRelease > 0 then begin success := success and RegQueryDWordValue(HKLM, key, 'Release', release); success := success and (release >= versionRelease); end; result := success and (install = 1) and (serviceCount >= service);end;
function InitializeSetup: Boolean; var Path:string; ResultCode: Integer; begin if IsDotNetDetected('v4.5.2', 0) then begin if RegValueExists(HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall{01FAEC41-B3BC-44F4-B185-5E8475AEB855}', 'Version') then begin Result := true; end else begin if MsgBox('系统检测到您没有安装VC++环境,是否立刻下载并安装?', mbConfirmation, MB_YESNO) = idYes then begin Path := ExpandConstant('{pf}/Internet Explorer/iexplore.exe'); Exec(Path, 'https://www.php.cn/link/daaf13a1565b64dc3779f551de67b95e', '', SW_SHOWNORMAL, ewWaitUntilTerminated, ResultCode); MsgBox('请安装好VC++环境后,再运行本安装包程序!',mbInformation,MB_OK); Result := false; end else begin MsgBox('没有安装VC++环境,无法运行程序,本安装程序即将退出!',mbInformation,MB_OK); Result := false; end; end; end else begin if MsgBox('系统检测到您没有安装.Net Framework4.5.2,是否立刻下载并安装?', mbConfirmation, MB_YESNO) = idYes then begin Path := ExpandConstant('{pf}/Internet Explorer/iexplore.exe'); Exec(Path, 'https://www.php.cn/link/493c4b304be1e32548b7ad5d5c22ef6b', '', SW_SHOWNORMAL, ewWaitUntilTerminated, ResultCode); MsgBox('请安装好.Net Framework环境后,再运行本安装包程序!',mbInformation,MB_OK); Result := false; end else begin MsgBox('没有安装.Net Framework环境,无法运行程序,本安装程序即将退出!',mbInformation,MB_OK); Result := false; end; end; end;












