问题描述
有没有办法使用 Inno Setup 删除 INI 文件中的注释?我们有一个正在运行更新的现有安装,但我们想使用 Inno Setup 安装程序删除现有注释。可用标志不能用于注释,只能用于设置:
Flags 这个参数是一组额外的选项。多个选项可能 通过用空格分隔它们来使用。以下选项是 支持:
createkeyifdoesntexist 仅当文件中不存在密钥时才分配给密钥。如果未指定此标志,则密钥将 不管它是否已经存在,都会被设置。
uninsdeleteentry 卸载程序时删除该条目。这可以与 uninsdeletesectionifempty 标志结合使用。
uninsdeletesection 卸载程序时,删除条目所在的整个部分。显然不会 在 Windows 本身使用的部分上使用它是个好主意 (就像 WIN.INI 中的某些部分)。你应该只在 您的应用程序专用的部分。
uninsdeletesectionifempty 与 uninsdeletesection 相同,但仅在其中没有键时才删除该部分。这个可以组合 带有 uninsdeleteentry 标志。
我想删除 ;
之后、文件末尾或 [Section]
之前以 [AnotherSection]
开头的任何行。
解决方法
使用这样的代码:
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',N]));
InSection := False;
end;
end;
end;
Inc(I);
end;
Inc(N);
end;
Result := SaveStringsToFileInCP(FileName,CP_UTF8);
if not Result then
begin
Log(Format('Error saving the file %s',[FileName]));
end;
end;
finally
Lines.Free;
end;
end;
LoadStringsFromFileInCP
和 SaveStringsToFileInCP
来自 Inno Setup - Convert array of string to Unicode and back to ANSI。不过,如果您不需要 UTF-8(毕竟纯 INI 文件使用 Ansi 编码),您可以使用内置的 LoadStringsFromFile
和 SaveStringsToFile
。
您可以在 DeleteIniSectionComments
或 ssInstall
步骤中从 CurStepChanged
event 调用 ssPostInstall
。
虽然imo,一旦你有这样的代码并且你的最终目标是实际删除整个部分,那么将代码更改为“删除包括评论在内的整个部分”是有意义的,而不仅仅是删除评论。