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

使用Inno Setup从注册表读取多路径实现文件复制的问题

解决Inno Setup中AutoCAD多版本多路径的文件复制问题

我在Inno Setup的[Files]区段中尝试将字体文件复制到AutoCAD各版本的对应目录,但每个AutoCAD版本(如R21.0)在注册表中对应多个子项路径,当前的GetDir函数仅返回其中一个路径,导致文件只复制到一个目录,无法覆盖所有实例。

原[Files]代码:

[Files]
Source: "Fonts\*"; DestDir: {code:GetDir|R21.0};
Source: "Fonts\*"; DestDir: {code:GetDir|R22.0};
Source: "Fonts\*"; DestDir: {code:GetDir|R23.1};
Source: "Fonts\*"; DestDir: {code:GetDir|R24.0};
Source: "Fonts\*"; DestDir: {code:GetDir|R24.1};

原GetDir函数:

function GetDir(AcadVerNames: string): String;
var
  AcadRegKey, sAcadLoc: String;
begin
  RootKeyU := HKEY_CURRENT_USER_64;  
   
  if RegGetSubkeyNames(RootKey, 'SOFTWARE\Autodesk\AutoCAD' + '\' + AcadVerNames, AcadVerKeysTemp) then
  begin
    for I := 0 to GetArrayLength(AcadVerKeysTemp)-1 do
    begin
      RegQueryStringValue(RootKeyU, 'SOFTWARE\Autodesk\AutoCAD' + '\' + AcadVerNames + '\'  + AcadVerKeysTemp[I] , 'RootFolder', sAcadLoc);
    end;
  end;
   
  Result := sAcadLoc + '\Fonts';
end;

问题根源

Inno Setup的[Files]区段中,{code:...}回调仅能返回单个字符串路径,因此即使函数遍历了多个注册表子项,最终只会返回最后一次循环得到的路径,无法实现多路径复制。

解决方案:手动遍历路径并复制文件

通过在安装阶段手动收集所有AutoCAD版本的Fonts路径,然后逐个复制文件,实现多路径覆盖。

步骤1:定义全局变量

在脚本的[Code]区段顶部定义全局数组,用于存储所有找到的Fonts路径:

var
  AcadFontPaths: TArrayOfString;
  I: Integer;

步骤2:编写路径收集函数

创建函数遍历注册表子项,收集所有对应版本的Fonts路径:

procedure CollectAcadFontPaths(AcadVerNames: string);
var
  AcadVerKeysTemp: TArrayOfString;
  sAcadLoc: String;
begin
  RootKeyU := HKEY_CURRENT_USER_64;  
  // 查询当前AutoCAD版本下的所有子项
  if RegGetSubkeyNames(RootKey, 'SOFTWARE\Autodesk\AutoCAD\' + AcadVerNames, AcadVerKeysTemp) then
  begin
    for I := 0 to GetArrayLength(AcadVerKeysTemp)-1 do
    begin
      // 尝试读取RootFolder值,成功则添加到路径数组
      if RegQueryStringValue(RootKeyU, 'SOFTWARE\Autodesk\AutoCAD\' + AcadVerNames + '\' + AcadVerKeysTemp[I], 'RootFolder', sAcadLoc) then
      begin
        SetArrayLength(AcadFontPaths, GetArrayLength(AcadFontPaths) + 1);
        AcadFontPaths[GetArrayLength(AcadFontPaths)-1] := sAcadLoc + '\Fonts';
      end;
    end;
  end;
end;

步骤3:在安装阶段执行复制

利用CurStepChanged事件,在安装步骤中收集所有路径并复制文件:

procedure CurStepChanged(CurStep: TSetupStep);
var
  FontSourcePath, DestPath, FilePath: String;
  FindRec: TFindRec;
begin
  if CurStep = ssInstall then
  begin
    // 初始化路径数组
    SetArrayLength(AcadFontPaths, 0);
    
    // 收集所有需要处理的AutoCAD版本路径
    CollectAcadFontPaths('R21.0');
    CollectAcadFontPaths('R22.0');
    CollectAcadFontPaths('R23.1');
    CollectAcadFontPaths('R24.0');
    CollectAcadFontPaths('R24.1');
    
    // 获取源字体文件路径
    FontSourcePath := ExpandConstant('{src}\Fonts');
    
    // 遍历源目录下的所有文件
    if FindFirst(FontSourcePath + '\*', FindRec) then
    begin
      repeat
        // 跳过目录,只处理文件
        if (FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
        begin
          FilePath := FontSourcePath + '\' + FindRec.Name;
          // 复制到每个目标Fonts目录
          for I := 0 to GetArrayLength(AcadFontPaths)-1 do
          begin
            DestPath := AcadFontPaths[I];
            // 确保目标目录存在
            if not DirExists(DestPath) then
              CreateDir(DestPath);
            // 复制文件(False表示覆盖已存在的文件)
            FileCopy(FilePath, DestPath + '\' + FindRec.Name, False);
          end;
        end;
      until not FindNext(FindRec);
      FindClose(FindRec);
    end;
  end;
end;

步骤4:移除原[Files]区段

因为已经通过代码手动处理文件复制,原[Files]中的相关条目可以删除,避免重复复制。

额外说明

  • 如果需要复制Fonts目录下的子目录及其中的文件,需要修改遍历逻辑,添加递归处理目录的代码。
  • 可以根据需求添加错误处理,比如复制失败时记录日志或提示用户。
  • 注册表根键可以根据系统位数调整(如HKEY_LOCAL_MACHINE或HKEY_CURRENT_USER_32),确保能正确读取到AutoCAD的安装路径。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 20:58:11