You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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;

使用说明

  1. 将上述代码复制到Inno Setup脚本的[Code]段中
  2. 用户启动安装程序时,InitializeSetup函数会自动触发CPU主频检查
  3. 若CPU主频未达标,将弹出错误提示并直接终止安装流程

代码说明

  • 完全对齐原C++代码的WMI查询逻辑,通过Win32_Processor类的MaxClockSpeed属性获取CPU最大主频
  • 包含COM初始化、安全配置、WMI连接、查询执行、结果遍历的完整流程
  • 加入资源自动释放逻辑,避免内存泄漏
  • 兼容多系统环境,忽略CoInitializeSecurity返回的已初始化错误

内容的提问来源于stack exchange,提问作者Tom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 18:25:54