2016-01-31 1 views
3

Je commence à utiliser Inno Setup et j'ai quelques problèmes avec mon encodage de fichier INI.
Je souhaite enregistrer l'entrée utilisateur dans le fichier INI et cette entrée peut contenir des accents.Enregistrer le fichier INI en UTF-8 plutôt qu'ANSI dans Inno Setup

J'utilise Inno Setup Unicode, mon setupScript.iss est UTF-8 encodées, et voici mon code (une partie):

[INI] 
Filename: "{app}\www\conf\config.ini"; Section: "Settings"; Key: "ca.plafondAnnuel"; String: "{code:GetUser|Plafond}" 
Filename: "{app}\www\conf\config.ini"; Section: "Settings"; Key: "app.siren"; String: "{code:GetUser|Siren}" 
Filename: "{app}\www\conf\config.ini"; Section: "Settings"; Key: "app.adresse"; String: "{code:GetUser|Adresse}" 


[Code] 
var 
    UserPage: TInputQueryWizardPage; 
    ExamplePage : TInputOptionWizardPage; 
    ImmatriculationPage : TInputOptionWizardPage; 
    FakeElemIndex: Integer; 
    FakeElem: TCustomEdit; 
    AdresseTextarea: TNewMemo; 

procedure InitializeWizard; 
begin 
    UserPage := CreateInputQueryPage(wpWelcome, 
    'Configuration de l''application', '', 
    'Configurez ici votre application. Une fois installée, vous pourrez modifier ces valeurs.'); 

    UserPage.Add('Siren :', False); 
    UserPage.Add('Plafond annuel (utilisé par les auto-entreprises, mettre 0 si vous ne souhaitez pas plafonner votre chiffre d''affaire.):', False); 

    FakeElemIndex := UserPage.Add('Votre adresse complète (telle qu''elle s''affichera sur les devis et factures, avec nom complet):', False); 
    FakeElem := UserPage.Edits[FakeElemIndex]; 

    AdresseTextarea := TNewMemo.Create(WizardForm); 
    AdresseTextarea.Parent := FakeElem.Parent; 
    AdresseTextarea.SetBounds(FakeElem.Left, FakeElem.Top, FakeElem.Width, ScaleY(50)); 

    // Hide the original single-line edit 
    FakeElem.Visible := False; 
end; 

function GetUser(Param: String): String; 
begin 
    if Param = 'Adresse' then 
    Result := AdresseTextarea.Text 
    else if Param = 'Siren' then 
    Result := UserPage.Values[0] 
    else if Param = 'Plafond' then 
    Result := UserPage.Values[1]; 
end; 

La valeur retournée par getUser|Adresse dans la partie [INI] n'est pas UTF- 8 encoded: J'ouvre le fichier INI avec Notepad ++ et je vois que le fichier est codé en UTF-8. Mais la valeur adresse est encodée en ANSI (Si je change le codage du fichier en ANSI, cette valeur est lisible)

Quelqu'un peut m'aider à comprendre comment puis-je sauvegarder cette entrée de l'utilisateur en UTF-8?

Merci beaucoup!

+0

Notez que vous ne devriez pas utiliser UTF-8 dans le code. Citant l'article [Unicode Inno Setup] (http://www.jrsoftware.org/ishelp/index.php?topic=unicode): * ... prend en charge Unicode, mais pas pour sa source d'entrée. Cela signifie qu'il utilise les types de chaînes Unicode comme indiqué, mais tous les caractères Unicode littéraux du script seront convertis en ANSI. Cela ne signifie pas que vous ne pouvez pas afficher les chaînes Unicode: vous pouvez par exemple utiliser des caractères Unicode codés pour construire des chaînes Unicode (comme 'S: = # $ 0100 + # $ 0101 + 'Aa';'), ou charger la chaîne depuis un fichier utilisant 'LoadStringsFromFile' ou une constante' {cm: ...} '. * –

+0

Merci pour vos réponses Martin. Je dois utiliser UTF8 parce que j'ai fait une application Web dans utf8 sans penser que je pourrais l'installer comme une application de bureau plus tard. Donc, le fichier ini conf doit aussi être en utf8, pour être lu correctement par mon application web. Donc, je dois être capable d'écrire dans ce fichier ini en UTF8, pas ANSI. – wyllyjon

Répondre

2

Les fonctions INI de Inno Setup (section [INI] et fonctions SetIni*) utilisent en interne la fonction Windows API WritePrivateProfileString.

Cette fonction ne prend pas en charge le format UTF-8. Tout ce qu'il supporte est le codage ANSI et UTF-16.
Voir How to read/write Chinese/Japanese characters from/to INI files?

Il est même douteux que l'application cible sera en mesure de lire le fichier INI UTF-8 codé, si elle repose sur la fonction API Windows pour lire.


Quoi qu'il en soit, si vous avez besoin UTF-8 vous devez formater les entrées au format INI vous et utiliser SaveStringsToUTF8File function pour l'écrire.


La dernière option est de le pirater en utilisant l'appel système WritePrivateProfileString d'écrire apparemment chaîne ANSI codé, qui sera en fait UTF-8 codé.

Pour cela, vous devez convertir la chaîne en UTF-8 dans votre code. Vous pouvez utiliser WideCharToMultiByte pour cela.

function WideCharToMultiByte(CodePage: UINT; dwFlags: DWORD; 
    lpWideCharStr: string; cchWideChar: Integer; lpMultiByteStr: AnsiString; 
    cchMultiByte: Integer; lpDefaultCharFake: Integer; 
    lpUsedDefaultCharFake: Integer): Integer; 
    external '[email protected] 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 '[email protected] 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

J'ai simplifié le code en utilisant 'WideCharToMultiByte'. –

+0

Merci Martin! J'ai essayé votre dernière solution, mais je ne sais pas si je l'utilise correctement. J'ai ajouté les fonctions à la fin du fichier iss (toujours dans la partie "Code"). J'ai laissé la partie [INI] (parce qu'elle n'écrit rien si je l'enlève). Peut-être que j'ai fait quelque chose de mal? Le texte ajouté à mon fichier ini est toujours codé ANSI. – wyllyjon

+0

Je ne suis pas certain de comprendre. Avez-vous supprimé la section '[INI]' ou non? Vous devez l'enlever. –