NSIS WriteINIStr Unicode

Я пытаюсь создать установщик NSIS для написанного мной приложения.

Программа установки берет ряд сведений о пользователе и записывает их в INI-файл. Проблема, с которой я сейчас сталкиваюсь, заключается в том, что созданный файл INI имеет формат ASCII. Это означает, что если пользователь вводит что-либо в формате Unicode или на неподдерживаемом языке, я получаю ???? в файле ini.

Как использовать NSIS для записи INI-файлов в формате Unicode?

Обновление 1: Итак, заметив, что есть новая версия NSIS (v3.0a), в которой есть больше возможностей для Unicode, я решил установить ее, чтобы посмотреть, работает ли она.

Предыдущий код приложения полностью совместим, и исполняемый файл был собран, но остается проблема, заключающаяся в том, что WriteINIStr не записывает юникод.


person Matt Seymour    schedule 03.07.2013    source источник


Ответы (2)


Если вы используете последнюю стабильную версию 2.46, NSIS не поддерживает юникод, и вам придется создать файл .ini самостоятельно с помощью FileOpen/FileWrite/FileClose и преобразовать текст с помощью системного плагина.

Есть долгожданная ветка юникода, которая зреет с 2009 года и я не заметил, что появилась v 3.0a0 был только что выпущен и доступен на сайте загрузки. (До этого вам нужно было проверить код и собрать двоичные файлы самостоятельно).

Вы должны дать ему попробовать с ним.

Редактировать: я сделал небольшой скрипт, чтобы продемонстрировать, как написать текстовый файл UTF-16le «вручную» с помощью NSIS 2.46, вы можете попробовать, если ваша строка с «экзотичными» символами из текстового поля правильно записано в тестовый файл

!include LogicLib.nsh
Name "unicode246"
OutFile unicode246.exe
ShowInstDetails show

Section

    StrCpy $1 "héhé © reçu" ;some "exotic" french chars
    StrLen $2 $1

    System::Call "*(&w${NSIS_MAX_STRLEN} r1)i.s"    ;allocate a buffer and write in wide char
    Pop $0  ;get the buffer address

    FileOpen $9 $EXEDIR\test.txt w ;Opens a file for writing

    ;write UTF-16LE BOM
    FileWriteByte $9 "255"
    FileWriteByte $9 "254"

    ;compute the buffer byte size
    IntOp $2 $2 * 2
    IntOp $2 $2 - 1

    ;loop on the bytes
    ${forEach} $1 0 $2 + 1
        IntOp $3 $0 + $1    ;compute the address of the nth byte

        System::Call "*$3(&i1 .r4)" ;read the byte in $4
        DetailPrint "address $0 + $1 = $3 = $4"
        FileWriteByte $9 $4
    ${next}
    FileClose $9
    System::Free $0 ;free buffer
SectionEnd
person Seki    schedule 03.07.2013
comment
Я только что попробовал ветку unicode, но обнаружил, что WriteINIStr по-прежнему работает только с ASCII (как это раздражает). Вскоре я попробую ваше предложение. - person Matt Seymour; 03.07.2013
comment
Вы явно включили Unicode? если альфа-версия 3.0 вам не подходит, есть также форк Unicode версии 2.46 для nsis. - person idleberg; 03.07.2013
comment
Сделал прототип для создания файла utf16-le из nsis 2.46, надеюсь поможет - person Seki; 03.07.2013
comment
Спасибо, @seki, я дам тебе знать, как у меня дела. - person Matt Seymour; 03.07.2013
comment
@idleberg Я изучил вилку Unicode, но WriteINIStr все еще был только в ascii. - person Matt Seymour; 03.07.2013
comment
@MattWritesCode: кстати, пробовали ли вы написать файл .ini с символами юникода самостоятельно (например, с помощью Scintilla / UltraEdit / чего-то еще), если он работает должным образом программой, которая читает файл .ini? - person Seki; 03.07.2013

WriteINIStr вызывает WritePrivateProfileString, и хотя версия Unicode (WritePrivateProfileStringW) по умолчанию также записывается как ansi, она будет записываться как UTF16LE если файл .ini имеет спецификацию.

Таким образом, вы можете использовать базовые функции файла NSIS *, чтобы увидеть, есть ли спецификация, если нет, вы можете добавить ее перед использованием команд ini...

person Anders    schedule 03.07.2013