1
votes

Is there a way to delete a comment in an INI file using Inno Setup? We have an existing installation that we are running an update on but we want to delete existing comments using the Inno Setup installer. The available flags don't see to work with comments, just settings:

Flags This parameter is a set of extra options. Multiple options may be used by separating them by spaces. The following options are supported:

createkeyifdoesntexist Assign to the key only if the key doesn't already exist in the file. If this flag is not specified, the key will be set regardless of whether it already existed.

uninsdeleteentry Delete the entry when the program is uninstalled. This can be combined with the uninsdeletesectionifempty flag.

uninsdeletesection When the program is uninstalled, delete the entire section in which the entry is located. It obviously wouldn't be a good idea to use this on a section that is used by Windows itself (like some of the sections in WIN.INI). You should only use this on sections private to your application.

uninsdeletesectionifempty Same as uninsdeletesection, but deletes the section only if there are no keys left in it. This can be combined with the uninsdeleteentry flag.


I want to delete any line starting with ; after [Section], before end of the file or [AnotherSection].

1

1 Answers

1
votes

Use a code like this:

const
  CP_UTF8 = 65001;

function DeleteIniSectionComments(Section, FileName: string): Boolean;
var
  Lines: TStrings;
  InSection: Boolean;
  Line: string;
  I, N: Integer;
begin
  Result := False;
  Lines := TStringList.Create;
  try
    if not LoadStringsFromFileInCP(FileName, Lines, CP_UTF8) then
    begin
      Log(Format('Error loading the file %s', [FileName]));
    end
      else
    begin
      Log(Format('Loading file %s with %d lines', [FileName, Lines.Count]));
      InSection := False;
      N := 1;
      I := 0;
      while I < Lines.Count do
      begin
        Line := Trim(Lines[I]);
        if (Line = '') or (Line[1] = ';') then
        begin
          if InSection then
          begin
            Log(Format('Deleting empty or comment line %d', [N]));
            Lines.Delete(I);
          end
            else
          begin
            Inc(I);
          end;
        end
          else
        begin
          if (Line[1] = '[') and (Line[Length(Line)] = ']') then
          begin
            if CompareText(Trim(Copy(Line, 2, Length(Line) - 2)), Section) = 0 then
            begin
              Log(Format('Found section %s at line %d', [Section, N]));
              InSection := True;
            end
              else
            begin
              if InSection then
              begin
                Log(Format('Section %s ends at line %d', [Section, N]));
                InSection := False;
              end;
            end;
          end;
          Inc(I);
        end;
        Inc(N);
      end;

      Result := SaveStringsToFileInCP(FileName, Lines, CP_UTF8);
      if not Result then
      begin
        Log(Format('Error saving the file %s', [FileName]));
      end;
    end;
  finally
    Lines.Free;
  end;
end;

LoadStringsFromFileInCP and SaveStringsToFileInCP come from Inno Setup - Convert array of string to Unicode and back to ANSI. Though if you do not need UTF-8 (pure INI files after all use Ansi encoding), you can do with the built-in LoadStringsFromFile and SaveStringsToFile.

You can call the DeleteIniSectionComments from CurStepChanged event in ssInstall or ssPostInstall step.

Though imo, once you have a code like this and your ultimate goal is to actually delete whole section, it would make sense to change the code to "delete whole section including comments", not just deleting the comments.