feat: Check MSVC redist version in WiX installer

This commit is contained in:
Nick Bolton 2025-03-11 14:53:48 +00:00 committed by Chris Rizzitello
parent cd45164e40
commit 57d1e42eca
8 changed files with 144 additions and 8 deletions

View file

@ -94,6 +94,8 @@ set(REQUIRED_OPENSSL_VERSION 3.0)
set(REQUIRED_LIBEI_VERSION 1.3) set(REQUIRED_LIBEI_VERSION 1.3)
set(REQUIRED_LIBPORTAL_VERSION 0.8) set(REQUIRED_LIBPORTAL_VERSION 0.8)
set(REQUIRED_QT_VERSION 6.7.0) set(REQUIRED_QT_VERSION 6.7.0)
set(REQUIRED_MSVC_RUNTIME_MAJOR 14)
set(REQUIRED_MSVC_RUNTIME_MINOR 42)
# Control debug item visibility # Control debug item visibility
# When not set logging is forced to DEBUG and show code locations # When not set logging is forced to DEBUG and show code locations

View file

@ -26,6 +26,7 @@
"Hadzhylov", "Hadzhylov",
"Hetu", "Hetu",
"HINSTANCE", "HINSTANCE",
"HKLM",
"hotspots", "hotspots",
"Hutterer", "Hutterer",
"ifdef", "ifdef",
@ -65,6 +66,7 @@
"qobject", "qobject",
"qputenv", "qputenv",
"readf", "readf",
"Redist",
"Regen", "Regen",
"Repology", "Repology",
"Rizzitello", "Rizzitello",

View file

@ -53,3 +53,18 @@ configure_file(
# This patch set ups filewall rules, the service and msm module # This patch set ups filewall rules, the service and msm module
set(CPACK_WIX_PATCH_FILE "${CMAKE_CURRENT_BINARY_DIR}/wix-patch.xml") set(CPACK_WIX_PATCH_FILE "${CMAKE_CURRENT_BINARY_DIR}/wix-patch.xml")
# Creates a DLL that can be used by our MSI for custom actions.
configure_file(
${MY_DIR}/wix-custom.h.in
${CMAKE_CURRENT_BINARY_DIR}/wix-custom.h @ONLY
)
add_library(
wix-custom SHARED
${MY_DIR}/wix-custom.cpp
)
target_include_directories(wix-custom PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
set_target_properties(wix-custom PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
)
target_link_libraries(wix-custom PRIVATE Msi)

View file

@ -0,0 +1,72 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2025 Symless Ltd.
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#include "wix-custom.h"
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
// Include after Windows.h
#include <MsiQuery.h>
#include <stdio.h>
#include <string>
namespace {
// Warning: DLL will crash with error code 1603 if we exceed this.
const auto kLogLineMax = 1024;
// Prefixes log messages with the app name so they're easier to find/filter.
const std::string kLogPrefix = std::string(kAppId) + " installer: ";
// Note: Resized to log line max when used.
static std::string s_logMessageBuffer; // NOSONAR - Must be mutable.
} // namespace
// This log output can be viewed by using the DebugView program.
#define MS_LOG_DEBUG(message, ...) \
s_logMessageBuffer.resize(kLogLineMax); \
sprintf(s_logMessageBuffer.data(), message, __VA_ARGS__); \
OutputDebugStringA((kLogPrefix + s_logMessageBuffer + "\n").c_str())
extern "C" __declspec(dllexport) UINT __stdcall CheckVCRedist(MSIHANDLE hInstall)
{
const auto kKeyName = TEXT("SOFTWARE\\Microsoft\\VisualStudio\\14.0\\VC\\Runtimes\\x64");
const auto kValueName = TEXT("Minor");
const auto kProperty = "VC_REDIST_VERSION_OK";
MS_LOG_DEBUG("checking for msvc redist v%d.%d", kWindowsRuntimeMajor, kWindowsRuntimeMinor);
HKEY hKey;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, kKeyName, 0, KEY_READ, &hKey) != ERROR_SUCCESS) {
MS_LOG_DEBUG("msvc redist registry key not found");
return ERROR_FUNCTION_FAILED;
}
MS_LOG_DEBUG("msvc redist registry key found, querying minor version");
DWORD minorVersion = 0;
DWORD size = sizeof(DWORD);
RegQueryValueEx(hKey, kValueName, nullptr, nullptr, (LPBYTE)&minorVersion, &size);
RegCloseKey(hKey);
MS_LOG_DEBUG("msvc redist minor version: %lu", minorVersion);
if (minorVersion < kWindowsRuntimeMinor) {
MS_LOG_DEBUG("msvc redist minor version %lu too low, expected >= %d", minorVersion, kWindowsRuntimeMinor);
// Returning success allows the installer will show a friendly error message.
return ERROR_SUCCESS;
}
MS_LOG_DEBUG("msvc redist version ok, setting: %s", kProperty);
if (MsiSetProperty(hInstall, kProperty, "ok") != ERROR_SUCCESS) {
MS_LOG_DEBUG("failed to set property: %s", kProperty);
return ERROR_FUNCTION_FAILED;
}
MS_LOG_DEBUG("msvc redist version check successful");
return ERROR_SUCCESS;
}

View file

@ -0,0 +1,14 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2025 Symless Ltd.
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#pragma once
const auto kAppId = "@CMAKE_PROJECT_NAME@";
// clang-format off
const auto kWindowsRuntimeMajor = @REQUIRED_MSVC_RUNTIME_MAJOR@;
const auto kWindowsRuntimeMinor = @REQUIRED_MSVC_RUNTIME_MINOR@;
// clang-format on

View file

@ -32,20 +32,42 @@
<RegistrySearch <RegistrySearch
Id="FindVCRedist" Id="FindVCRedist"
Root="HKLM" Root="HKLM"
Key="SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64" Key="SOFTWARE\Microsoft\VisualStudio\@REQUIRED_MSVC_RUNTIME_MAJOR@.0\VC\Runtimes\x64"
Name="Installed" Name="Installed"
Type="raw" /> Type="raw" />
</Property> </Property>
<CustomAction Id="Run_Deskflow" ExeCommand="Deskflow" FileRef="CM_FP_deskflow.exe" Return="asyncNoWait"/> <Binary Id="CustomDLL" SourceFile="@CMAKE_CURRENT_BINARY_DIR@/wix-custom.dll" />
<CustomAction
Id="CheckVCRedist"
BinaryRef="CustomDLL"
DllEntry="CheckVCRedist"
Execute="immediate" />
<CustomAction <CustomAction
Id="ShowVCRedistError" Id="ShowVCRedistError"
Error="Latest Microsoft Visual C++ Redistributable is required. Please install it before proceeding."/> Error="Microsoft Visual C++ Redistributable v@REQUIRED_MSVC_RUNTIME_MAJOR@.@REQUIRED_MSVC_RUNTIME_MINOR@ or later is required. Please download and install the latest version and then restart the installation. See our documentation for instructions." />
<CustomAction
Id="RunDeskflow"
ExeCommand="Deskflow"
FileRef="CM_FP_deskflow.exe"
Return="asyncNoWait" />
<InstallExecuteSequence> <InstallExecuteSequence>
<Custom Action="ShowVCRedistError" Before="InstallServices" Condition="NOT Installed AND NOT VC_REDIST_INSTALLED"/> <Custom
<Custom Action="Run_Deskflow" OnExit="success" Condition="NOT Installed"/> Action="CheckVCRedist"
Before="InstallInitialize"
Condition="NOT Installed AND VC_REDIST_INSTALLED" />
<Custom
Action="ShowVCRedistError"
Before="InstallInitialize"
Condition="NOT Installed AND (NOT VC_REDIST_INSTALLED OR NOT VC_REDIST_VERSION_OK)" />
<Custom
Action="RunDeskflow"
OnExit="success"
Condition="NOT Installed" />
</InstallExecuteSequence> </InstallExecuteSequence>
</CPackWiXFragment> </CPackWiXFragment>
</CPackWiXPatch> </CPackWiXPatch>

View file

@ -20,8 +20,8 @@
// See table of the compiler versions and the matching runtime DLL versions: // See table of the compiler versions and the matching runtime DLL versions:
// https://dev.to/yumetodo/list-of-mscver-and-mscfullver-8nd // https://dev.to/yumetodo/list-of-mscver-and-mscfullver-8nd
#if _MSC_VER >= 1942 // Visual Studio 2022 Update 12 (v17.12.4) #if _MSC_VER >= 1942 // Visual Studio 2022 Update 12 (v17.12.4)
const auto kRequiredMajor = 14; const auto kRequiredMajor = kWindowsRuntimeMajor;
const auto kRequiredMinor = 42; const auto kRequiredMinor = kWindowsRuntimeMinor;
#elif _MSC_VER >= 1920 // Visual Studio 2019 Update 7 (v16.7) #elif _MSC_VER >= 1920 // Visual Studio 2019 Update 7 (v16.7)
const auto kRequiredMajor = 14; const auto kRequiredMajor = 14;
const auto kRequiredMinor = 27; const auto kRequiredMinor = 27;

View file

@ -39,3 +39,12 @@ const auto kTlsCertificateFilename = "@CMAKE_PROJECT_NAME@.pem";
const auto kTlsFingerprintLocalFilename = "local-fingerprint"; const auto kTlsFingerprintLocalFilename = "local-fingerprint";
const auto kTlsFingerprintTrustedServersFilename = "trusted-servers"; const auto kTlsFingerprintTrustedServersFilename = "trusted-servers";
const auto kTlsFingerprintTrustedClientsFilename = "trusted-clients"; const auto kTlsFingerprintTrustedClientsFilename = "trusted-clients";
#ifdef _WIN32
// clang-format off
const auto kWindowsRuntimeMajor = @REQUIRED_MSVC_RUNTIME_MAJOR@;
const auto kWindowsRuntimeMinor = @REQUIRED_MSVC_RUNTIME_MINOR@;
// clang-format on
#endif