Copy files to several destinations read from registry using Inno Setup

120 Views Asked by At

I'm using these lines in [Files] section to copy files to directories of installed versions of a software, while each version has several addresses: (For example R21.0 is a version of the software)

[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};

This is GetDir function:

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;

The problem is that there are two results for AcadVerNames, in another words two location for each version. This function returns just one destination of subfolder in a version

With this system, just two versions are installed and destinations for copying files stored in subfolders of each version, the subfolders are not fixed, each version may have one, two or three subfolders in registry.

enter image description here

1

There are 1 best solutions below

0
Martin Prikryl On

You can use a solution like this:
How to install same file to multiple locations (Inno Setup)

You just need an additional parameter to query n-th directory for each version.

Something like this:

[Files]
Source: "Fonts\*"; DestDir: {code:GetDir|R21.0,0}; Check: HasDir('R21.0', 0)
Source: "Fonts\*"; DestDir: {code:GetDir|R21.0,1}; Check: HasDir('R21.0', 1)
Source: "Fonts\*"; DestDir: {code:GetDir|R21.0,2}; Check: HasDir('R21.0', 2)
const
  AcadRegRoot = HKCU64;
  AcadRegKeyRoot = 'SOFTWARE\Autodesk\AutoCAD';

function GetDir(Param: string): string;
var
  AcadRegKey: string;
  Names: TArrayOfString;
  I, P: Integer;
begin
  P := Pos(',', Param);
  AcadVerNames := Copy(Param, 1, P - 1);
  AcadRegKey := AcadRegKeyRoot + '\' + AcadVerNames;
  if RegGetSubkeyNames(AcadRegRoot, AcadRegKey, Names) then
  begin
    I := StrToInt(Copy(Param, P + 1, Length(Param) - P));
    AcadRegKey := AcadRegKey + '\' + Names[I];

    if RegQueryStringValue(AcadRegRoot, AcadRegKey, 'RootFolder', Result) then
      Result := Result + '\Fonts';
  end;
end;

function HasDir(AcadVerNames: string; I: Integer): Boolean;
var
  AcadRegKey: string;
  Names: TArrayOfString;
begin
  AcadRegKey := AcadRegKeyRoot + '\' + AcadVerNames;
  Result :=
    RegGetSubkeyNames(AcadRegRoot, AcadRegKey, Names) and
    (GetArrayLength(Names) > I);
end;

And the similarly as shown there, you can use preprocessor to avoid repetitions:

[Files]
#define FontsForReleaseN(Ver, N) \
  "Source: ""Fonts\*""; DestDir: {code:GetDir|" + Ver + "," + Str(N) +"}; " + \
  "Check: HasDir('" + Ver + "'," + Str(N) + ")" + NewLine
#define FontsForRelease(Ver) \
  FontsForReleaseN(Ver, 0) + FontsForReleaseN(Ver, 1) + FontsForReleaseN(Ver, 2)

#emit FontsForRelease('R21.0')
#emit FontsForRelease('R22.0')
#emit FontsForRelease('R23.1')
...

Not tested, but it should give you the idea.


Other option is to give up on Files section and install everything using the Pascal code. It's more straightforward. But it's more complicated, if you need to show the progress in the GUI.