1

I want to edit a JSON file with Inno Setup for entering the installation path of my programme.

I have also found the post: How to parse a JSON string in Inno Setup? however, I can't cope with it because it talks about Info, User & String, but I only have Info & User.

This is what the entry that needs to be edited looks like:

  "game_dirs": [
    "Installation path"
  ]

This is my code:

[Code]
function JSONQueryString(FileName, Section, Key, Default: WideString;
  var Value: WideString; var ValueLength: Integer): Boolean;
  external 'JSONQueryString@files:jsonconfig.dll stdcall';
function JSONQueryBoolean(FileName, Section, Key: WideString; 
  Default: Boolean; var Value: Boolean): Boolean;
  external 'JSONQueryBoolean@files:jsonconfig.dll stdcall';
function JSONQueryInteger(FileName, Section, Key: WideString; 
  Default: Int64; var Value: Int64): Boolean;
  external 'JSONQueryInteger@files:jsonconfig.dll stdcall';
function JSONWriteString(FileName, Section, Key, 
  Value: WideString): Boolean;
  external 'JSONWriteString@files:jsonconfig.dll stdcall';
function JSONWriteBoolean(FileName, Section, Key: WideString;
  Value: Boolean): Boolean;
  external 'JSONWriteBoolean@files:jsonconfig.dll stdcall';
function JSONWriteInteger(FileName, Section, Key: WideString;
  Value: Int64): Boolean;
  external 'JSONWriteInteger@files:jsonconfig.dll stdcall';

function BoolToStr(Value: Boolean): string;
begin
  Result := 'True';
  if not Value then
    Result := 'False';
end;

procedure InitializeWizard;
var
  FileName: WideString;
  IntValue: Int64;
  StrValue: WideString;
  StrLength: Integer;
  BoolValue: Boolean;
begin
  { set the source JSON config file path }
  FileName := '{app}\\PATH\\Config.json';
  { allocate string buffer to enough length }
  SetLength(StrValue, 16);
  { set the buffer length value }
  StrLength := Length(StrValue);
  { query string value }
  if JSONQueryString(FileName, 'game_dirs', '{app}\TEST', 'Default', StrValue, 
    StrLength)
  then
    MsgBox('Section_1:Key_1=' + StrValue, mbInformation, MB_OK);
  { query integer value }
  if JSONQueryInteger(FileName, 'Section_1', 'Key_2', 0, IntValue) then
    MsgBox('Section_1:Key_2=' + IntToStr(IntValue), mbInformation, MB_OK);
  { query boolean value }
end;

The following error message appears during installation:

Runtime error (at 46:224): Could not call proc.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Michael D.
  • 11
  • 2

1 Answers1

0

Your game_dirs element is a JSON array. I do not think that JSONConfig.dll supports arrays.

You can use JsonParser library instead. With use of additional functions from my answer to How to parse a JSON string in Inno Setup?, the code can be like:

function FindJsonArray(
  Output: TJsonParserOutput; Parent: TJsonObject; Key: TJsonString;
  var Arr: TJsonArray): Boolean;
var
  JsonValue: TJsonValue;
begin
  Result :=
    FindJsonValue(Output, Parent, Key, JsonValue) and
    (JsonValue.Kind = JVKArray);
  if Result then
  begin
    Arr := Output.Arrays[JsonValue.Index];
  end;
end;

procedure EditGameDirs(FileName: string; GameDir: string);
var
  JsonLines: TStringList;
  JsonParser: TJsonParser;
  JsonRoot: TJsonObject;
  GameDirs: TJsonArray;
begin
  JsonLines := TStringList.Create;
  JsonLines.LoadFromFile(FileName);

  if ParseJsonAndLogErrors(JsonParser, JsonLines.Text) then
  begin
    JsonRoot := GetJsonRoot(JsonParser.Output);
    if not FindJsonArray(JsonParser.Output, JsonRoot, 'game_dirs', GameDirs) then
    begin
      Log('Cannot find game_dirs');
    end
      else
    if (GetArrayLength(GameDirs) <> 1) or
       (GameDirs[0].Kind <> JVKString) then
    begin
      Log('game_dirs does not have one string element');
    end
      else
    begin
      Log(Format('Previous game_dirs was [%s]', [
        JsonParser.Output.Strings[GameDirs[0].Index]]));
      Log(Format('New game_dirs is [%s]', [GameDir]));
      JsonParser.Output.Strings[GameDirs[0].Index] := GameDir;
      JsonLines.Clear;
      PrintJsonParserOutput(JsonParser.Output, JsonLines);
      JsonLines.SaveToFile(FileName + '2');
    end;
  end;
end;  
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992