How to pre-check in Inno Setup that CPU has at least 1.5GHz (per single core), so that user is not disappointed, when installing my app to their device and it would be too slow?
This code should do it in C++, but how can I convert this to Inno Setup's Pascal script?
#include <iostream>
#include <windows.h>
#include <comdef.h>
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
bool IsCpuAtLeast1_5GHz() {
HRESULT hres;
// Initialize COM.
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres)) {
std::cout << "Failed to initialize COM library. Error code = 0x"
<< std::hex << hres << std::endl;
return false;
}
// Initialize security.
hres = CoInitializeSecurity(
NULL,
-1, // COM authentication
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
);
if (FAILED(hres)) {
std::cout << "Failed to initialize security. Error code = 0x"
<< std::hex << hres << std::endl;
CoUninitialize();
return false;
}
// Obtain the initial locator to WMI.
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *)&pLoc);
if (FAILED(hres)) {
std::cout << "Failed to create IWbemLocator object. "
<< "Error code = 0x"
<< std::hex << hres << std::endl;
CoUninitialize();
return false;
}
// Connect to WMI.
IWbemServices *pSvc = NULL;
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"), // WMI namespace
NULL, // User name (NULL = current user)
NULL, // User password (NULL = current user)
0, // Locale
NULL, // Security flags
0, // Authority
0, // Context object
&pSvc // IWbemServices proxy
);
if (FAILED(hres)) {
std::cout << "Could not connect to WMI. Error code = 0x"
<< std::hex << hres << std::endl;
pLoc->Release();
CoUninitialize();
return false;
}
// Set security levels on the proxy.
hres = CoSetProxyBlanket(
pSvc, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL, // Client identity
EOAC_NONE // Proxy capabilities
);
if (FAILED(hres)) {
std::cout << "Could not set proxy blanket. Error code = 0x"
<< std::hex << hres << std::endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return false;
}
// Use the IWbemServices pointer to make requests of WMI.
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT MaxClockSpeed FROM Win32_Processor"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres)) {
std::cout << "WMI query failed. Error code = 0x"
<< std::hex << hres << std::endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return false;
}
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
// Get the data from the query.
while (pEnumerator) {
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if (0 == uReturn) {
break;
}
VARIANT vtProp;
hr = pclsObj->Get(L"MaxClockSpeed", 0, &vtProp, 0, 0);
// Check if the clock speed is greater than or equal to 1500 MHz.
if (vtProp.intVal >= 1500) {
pclsObj->Release();
pSvc->Release();
pLoc->Release();
CoUninitialize();
return true;
}
pclsObj->Release();
}
// Cleanup.
pSvc->Release();
pLoc->Release();
pEnumerator->Release();
CoUninitialize();
return false;
}
int main() {
if (IsCpuAtLeast1_5GHz()) {
std::cout << "CPU is 1.5 GHz or higher." << std::endl;
} else {
std::cout << "
Building upon my answer to Is there a way to read the system's information in Inno Setup, you can use IDispatch COM automation code like this:
[Code]
function InitializeSetup: Boolean;
var
Query: string;
WbemLocator, WbemServices: Variant;
WbemObjectSet: Variant;
Processor: Variant;
Msg: string;
begin
Result := True;
WbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
WbemServices := WbemLocator.ConnectServer('.', 'root\CIMV2');
Query := 'SELECT MaxClockSpeed FROM Win32_Processor';
WbemObjectSet := WbemServices.ExecQuery(Query);
if VarIsNull(WbemObjectSet) or (WbemObjectSet.Count = 0) then
begin
Log('Cannot retrieve processor information');
end
else
begin
Processor := WbemObjectSet.ItemIndex(0);
if Processor.MaxClockSpeed >= 1500 then
begin
Log(Format('Processor max clock speed is %d, what is enough', [
Integer(Processor.MaxClockSpeed)]));
end
else
begin
Msg :=
'Your processor max clock speed is %.2f GHz, ' +
'what is not enough for this application. '#13#13 +
'Do you really want to continue with installation?';
Msg := Format(Msg, [Extended(Processor.MaxClockSpeed) / 1000]);
if MsgBox(Msg, mbConfirmation, MB_OKCANCEL) = IDCANCEL then
Result := False;
end;
end;
end;