Save INI file in UTF-8 rather than ANSI in Inno Setup

后端 未结 1 817
萌比男神i
萌比男神i 2021-01-14 18:03

I\'m starting to use Inno Setup, and I have some problems with my INI file encoding.
I want to save user input in the INI file, and this input can contain accents.

1条回答
  •  隐瞒了意图╮
    2021-01-14 18:23

    The INI functions of Inno Setup ([INI] section and SetIni* functions) use internally the Windows API function WritePrivateProfileString.

    This function does not support UTF-8 at all. All it supports is the ANSI encoding and UTF-16.
    See How to read/write Chinese/Japanese characters from/to INI files?

    So it's even questionable whether the target application will be able to read UTF-8-encoded INI file, if it relies on the Windows API function to read it.


    Anyway, if you need the UTF-8 you would have to format the entries to INI format yourself and use SaveStringsToUTF8File function to write it.


    The last option is to hack it by using the system call WritePrivateProfileString to write seemingly ANSI-encoded string, which will be in fact UTF-8-encoded.

    For that you need to convert the string to UTF-8 in your code. You can use WideCharToMultiByte for that.

    function WideCharToMultiByte(CodePage: UINT; dwFlags: DWORD;
      lpWideCharStr: string; cchWideChar: Integer; lpMultiByteStr: AnsiString;
      cchMultiByte: Integer; lpDefaultCharFake: Integer;
      lpUsedDefaultCharFake: Integer): Integer;
      external 'WideCharToMultiByte@kernel32.dll stdcall';
    
    const
      CP_UTF8 = 65001;
    
    function GetStringAsUtf8(S: string): AnsiString;
    var
      Len: Integer;
    begin
      Len := WideCharToMultiByte(CP_UTF8, 0, S, Length(S), Result, 0, 0, 0);
      SetLength(Result, Len);
      WideCharToMultiByte(CP_UTF8, 0, S, Length(S), Result, Len, 0, 0);
    end;
    
    function WritePrivateProfileString(
      lpAppName, lpKeyName, lpString, lpFileName: AnsiString): Integer;
      external 'WritePrivateProfileStringA@kernel32.dll stdcall';
    
    procedure CurStepChanged(CurStep: TSetupStep);
    var
      IniFileName: string;
    begin
      if CurStep = ssInstall then
      begin
        Log('Writting INI file');
        if not ForceDirectories(ExpandConstant('{app}\www\conf')) then
        begin
          MsgBox('Error creating directory for INI file', mbError, MB_OK);
        end
          else
        begin
          IniFileName := ExpandConstant('{app}\www\conf\config.ini');
          if (WritePrivateProfileString(
                'Settings', 'ca.plafondAnnuel', GetStringAsUtf8(GetUser('Plafond')),
                IniFileName) = 0) or
             (WritePrivateProfileString(
                'Settings', 'app.siren', GetStringAsUtf8(GetUser('Siren')),
                IniFileName) = 0) or
             (WritePrivateProfileString(
                'Settings', 'app.adresse', GetStringAsUtf8(GetUser('Adresse')),
                IniFileName) = 0) then
          begin
            MsgBox('Error writting the INI file', mbError, MB_OK);
          end;
        end;
      end;
    end;
    

    0 讨论(0)
提交回复
热议问题