如何在Inno Setup中预检查CPU单核心≥1.5GHz及转换C++代码为Pascal脚本
在Inno Setup中预先检查CPU主频是否≥1.5GHz
需求说明
需要在安装程序启动阶段检查用户CPU的单核心最大主频是否至少为1.5GHz,若不达标则终止安装并提示用户,避免后续运行卡顿。以下是将提供的C++ WMI查询逻辑转换为Inno Setup Pascal脚本的实现方案。
转换后的Pascal脚本实现
[Code] const RPC_C_AUTHN_WINNT = 10; RPC_C_AUTHZ_NONE = 0; RPC_C_AUTHN_LEVEL_CALL = 3; RPC_C_IMP_LEVEL_IMPERSONATE = 3; EOAC_NONE = 0; WBEM_FLAG_FORWARD_ONLY = $00000020; WBEM_FLAG_RETURN_IMMEDIATELY = $00000010; COINIT_MULTITHREADED = 0; type HRESULT = LongWord; IUnknown = interface ['{00000000-0000-0000-C000-000000000046}'] function QueryInterface(const IID: TGUID; out Obj): HRESULT; stdcall; function AddRef: Integer; stdcall; function Release: Integer; stdcall; end; IWbemLocator = interface(IUnknown) ['{DC12A687-737F-11CF-884D-00AA004B2E24}'] function ConnectServer(const strNetworkResource: WideString; const strUser: WideString; const strPassword: WideString; const strLocale: WideString; lSecurityFlags: LongWord; const strAuthority: WideString; pCtx: IUnknown; out ppNamespace: IUnknown): HRESULT; stdcall; end; IWbemServices = interface(IUnknown) ['{95BAB904-737F-11CF-884D-00AA004B2E24}'] function ExecQuery(const strQueryLanguage: WideString; const strQuery: WideString; lFlags: LongWord; pCtx: IUnknown; out ppEnum: IUnknown): HRESULT; stdcall; end; IEnumWbemClassObject = interface(IUnknown) ['{02799975-737F-11CF-884D-00AA004B2E24}'] function Next(lTimeout: LongWord; uCount: LongWord; out ppObjects: IUnknown; out uReturned: LongWord): HRESULT; stdcall; end; IWbemClassObject = interface(IUnknown) ['{DC12A689-737F-11CF-884D-00AA004B2E24}'] function Get(const strName: WideString; lFlags: LongWord; out pVal: OleVariant; pType: Pointer; pFlavor: Pointer): HRESULT; stdcall; end; function CoInitializeEx(pvReserved: Pointer; dwCoInit: LongWord): HRESULT; stdcall; external 'CoInitializeEx@ole32.dll stdcall'; function CoUninitialize: Integer; stdcall; external 'CoUninitialize@ole32.dll stdcall'; function CoCreateInstance(const clsid: TGUID; pUnkOuter: IUnknown; dwClsContext: LongWord; const iid: TGUID; out ppv): HRESULT; stdcall; external 'CoCreateInstance@ole32.dll stdcall'; function CoSetProxyBlanket(pProxy: IUnknown; dwAuthnSvc: LongWord; dwAuthzSvc: LongWord; pServerPrincName: PWideChar; dwAuthnLevel: LongWord; dwImpLevel: LongWord; pAuthInfo: Pointer; dwCapabilities: LongWord): HRESULT; stdcall; external 'CoSetProxyBlanket@ole32.dll stdcall'; function CoInitializeSecurity(pSecDesc: Pointer; cAuthSvc: LongWord; asAuthSvc: Pointer; pReserved: Pointer; dwAuthnLevel: LongWord; dwImpLevel: LongWord; pAuthInfo: Pointer; dwCapabilities: LongWord; pReserved3: Pointer): HRESULT; stdcall; external 'CoInitializeSecurity@ole32.dll stdcall'; function IsCpuAtLeast1500MHz: Boolean; var hRes: HRESULT; pLoc: IWbemLocator; pSvc: IWbemServices; pEnumerator: IEnumWbemClassObject; pclsObj: IWbemClassObject; uReturn: LongWord; vtProp: OleVariant; CLSID_WbemLocator: TGUID; IID_IWbemLocator: TGUID; IID_IWbemServices: TGUID; IID_IEnumWbemClassObject: TGUID; begin Result := False; // 初始化COM hRes := CoInitializeEx(nil, COINIT_MULTITHREADED); if Failed(hRes) then Exit; try // 初始化安全设置,忽略已初始化的错误 hRes := CoInitializeSecurity(nil, -1, nil, nil, 0, RPC_C_IMP_LEVEL_IMPERSONATE, nil, EOAC_NONE, nil); if Failed(hRes) and (hRes <> $80010119) then Exit; // 初始化CLSID和IID CLSIDFromString('{4590f811-1d3a-11d0-891f-00aa004b2e24}', CLSID_WbemLocator); CLSIDFromString('{DC12A687-737F-11CF-884D-00AA004B2E24}', IID_IWbemLocator); CLSIDFromString('{95BAB904-737F-11CF-884D-00AA004B2E24}', IID_IWbemServices); CLSIDFromString('{02799975-737F-11CF-884D-00AA004B2E24}', IID_IEnumWbemClassObject); // 创建WbemLocator实例 hRes := CoCreateInstance(CLSID_WbemLocator, nil, 1, IID_IWbemLocator, pLoc); if Failed(hRes) then Exit; // 连接到WMI命名空间 hRes := pLoc.ConnectServer('ROOT\CIMV2', '', '', '', 0, '', nil, pSvc); if Failed(hRes) then Exit; // 设置代理安全权限 hRes := CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nil, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, nil, EOAC_NONE); if Failed(hRes) then Exit; // 执行WQL查询获取CPU主频信息 hRes := pSvc.ExecQuery('WQL', 'SELECT MaxClockSpeed FROM Win32_Processor', WBEM_FLAG_FORWARD_ONLY or WBEM_FLAG_RETURN_IMMEDIATELY, nil, pEnumerator); if Failed(hRes) then Exit; // 遍历查询结果 while True do begin hRes := pEnumerator.Next($FFFFFFFF, 1, pclsObj, uReturn); if (uReturn = 0) or Failed(hRes) then Break; // 获取MaxClockSpeed属性值 hRes := pclsObj.Get('MaxClockSpeed', 0, vtProp, nil, nil); if Succeeded(hRes) then begin // 检查主频是否达标 if vtProp >= 1500 then begin Result := True; Break; end; end; pclsObj := nil; end; finally // 自动释放所有COM资源 pclsObj := nil; pEnumerator := nil; pSvc := nil; pLoc := nil; CoUninitialize; end; end; function InitializeSetup: Boolean; begin Result := True; // 安装前执行CPU检查 if not IsCpuAtLeast1500MHz then begin MsgBox('您的CPU主频低于1.5GHz,无法安装本应用。', mbError, MB_OK); Result := False; end; end;
使用说明
- 将上述代码复制到Inno Setup脚本的
[Code]段中 - 用户启动安装程序时,
InitializeSetup函数会自动触发CPU主频检查 - 若CPU主频未达标,将弹出错误提示并直接终止安装流程
代码说明
- 完全对齐原C++代码的WMI查询逻辑,通过
Win32_Processor类的MaxClockSpeed属性获取CPU最大主频 - 包含COM初始化、安全配置、WMI连接、查询执行、结果遍历的完整流程
- 加入资源自动释放逻辑,避免内存泄漏
- 兼容多系统环境,忽略
CoInitializeSecurity返回的已初始化错误
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

