InstallScript GetLine () не может прочитать текстовый файл, содержащий результат из командной строки - PullRequest
0 голосов
/ 03 мая 2018

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

// send command to cmd to execute and redirect the result to a text file

// try to read the file
szDir = "D:\\";
szFileName = "MyFile.txt";

if Is(FILEEXISTS, szDir ^ szFileName) then
    listID = ListCreate(STRINGLIST);
    if listID != LIST_NULL then
        if OpenFIleMode(FILE_MODE_NORMAL) = 0 then
            if OpenFile(nFileHandle, szDir, szFileName) = 0 then

                // I run into problem here
                while (GetLine(nFileHandle, szCurLine) = 0 )
                    ListAddString(listID, szCurLine, AFTER);
                endwhile;
                CloseFile(nFileHandle);

            endif;
        endif;
    endif;
endif;

Проблема в том, что сразу после запуска командной строки и перенаправления результата на MyFile.txt я могу установить режим открытия файла, открыть файл, но не могу прочитать любой текст в своем списке. ListReadFromFile() не помогает. Если я открою файл, отредактирую и сохраню его вручную, мой скрипт сработает.

После отладки я понял, что GetLine() возвращает код ошибки (-1), что означает, что указатель файла должен находиться в конце файла или других ошибок. Однако FILE_MODE_NORMAL устанавливает файл только для чтения и устанавливает указатель файла в начале файла.

Что я, возможно, сделал не так? Это как-то связано с доступом на чтение / запись к файлу? Я пробовал эту команду без результата:

icacls D:\MyFile.txt /grant Administrator:(R,W)

Я использую IstallShield 2018 и Windows 10, 64-разрядные, кстати. Ваша помощь очень ценится.

РЕДАКТИРОВАТЬ 1: Я подозревал кодировку и пробовал несколько вещей:

  1. После запуска «wslconfig / l» содержимое MyFile.txt, открытое в Notepad ++, не имеет кодировки, но все равно выглядит нормально и доступно для чтения. Я пытался преобразовать контент в UTF-8, но он не работал.

  2. Если я добавлю что-то в файл (echo, эта строка добавлена ​​>> MyFile.txt), кодировка изменится на UTF-8, но также изменится и содержимое шага 1. NULL (\ 0) добавляется между каждым символом и даже заменяет символ новой строки. Возможно, именно поэтому GetLine () не удалось прочитать файл.

  3. Обход: после шага 1 я запускаю «find» my_desired_content «MyFile.txt»> TempFile.txt и читаю TempFile.txt (который кодируется в UTF-8).

Моя конечная цель состоит в том, чтобы проверить, "my_desired_content" apeears в результате "wslconfig / l", так что это хорошо. Однако я не понимаю, что и MyFile.txt, и TempFile.txt создаются из команды cmd, но они кодируются по-разному?

Ответы [ 2 ]

0 голосов
/ 04 мая 2018

Вся эта вещь WSL довольно новая. Я не вижу каких-либо API-интерфейсов, а вместо вывода результатов команды очистки экрана, которые вы можете посмотреть в этом разделе реестра:

HKEY_CURRENT_USER \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Lxss

Кажется, есть список установленных дистрибутивов, которые приходят из магазина. Исходя из магазина, вероятно, объясняет, почему это HKCU, а не HKLM.

Прекрасный новый мир .... вздох.

0 голосов
/ 03 мая 2018

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

  • Его содержимое закодировано в UTF-16 (LE) без спецификации
  • Его новые строки кодируются как CR или CR CR вместо CR LF

Я думал, что новые строки будут важнее, чем кодировка текста, но, оказывается, у меня это было задом наперед. Если я изменяю каждую из этих вещей независимо, GetLine, кажется, работает правильно для CR, CR CR или CR LF, но обрабатывает UTF-16 только при наличии спецификации. (То есть в шестнадцатеричном редакторе файл начинается с FF FE 57 00 вместо 57 00 для файла, начинающегося с символа W.)

Я немного растерялся из-за лучшего способа решения этой проблемы. Если вы готовы принять вызов, вы можете прочитать файл с помощью FILE_MODE_BINARYREADONLY и использовать свои дополнительные знания о том, что должно быть в файле, чтобы убедиться, что вы правильно интерпретируете его кодировку. Обратите внимание, что для большей части UTF-16 вы можете создать одну единицу кода, комбинируя два байта следующим образом:

szResult[i] = (nHigh << 8) + nLow;

, где nHigh и nLow, вероятно, являются значениями, такими как szBuffer[2*i + 1] и szBuffer[2*i], при условии, что вы заполнили STRING szBuffer, вызвав ReadBytes.

Другие непроверенные идеи включают редактирование в двоичном виде для обеспечения наличия спецификации (FF FE), выяснение способов обеспечения первоначального создания файла с помощью спецификации, выяснение способов его создания в альтернативной кодировке, поиск другой команды Вы можете вызвать «исправить» файл или отправить запрос поставщику (моему работодателю) и надеяться, что команда разработчиков изменит что-то, чтобы лучше справиться с этим делом.


Вот более простое решение. Если вы можете с уверенностью предположить, что команда будет добавлять символы UTF-16 без подписи, вы можете добавить эти выходные данные в файл, который имеет только подпись. Как вы получаете такой файл?

  • Вы можете создать файл с только спецификацией в вашей среде разработки и добавить его в файлы поддержки. Если вам нужно использовать его несколько раз, сначала скопируйте его.
  • Вы можете создать его с помощью кода. Просто позвоните по следующему (проверка ошибок не включена для ясности)

    OpenFileMode(FILE_MODE_APPEND_UNICODE);
    CreateFile(nFileHandle, szDir, szFileName);
    CloseFile(nFileHandle);
    

    и если szDir ^ szFileName не существует, теперь это будет файл только с подписью UTF-16.

Предполагая, что этот файл называется sig.txt, вы можете затем вызвать команду wslconfig /l <strong>>> sig.txt</strong> для записи в этот файл. Обратите внимание на удвоенный >> для добавления. Полученный файл будет включать подпись Unicode, которую вы создали заранее, плюс вывод данных Unicode из wslconfig, и GetLine должен правильно интерпретировать вещи.

Самая большая проблема здесь в том, что это жестко закодировано вокруг поведения wslconfig, и это поведение может измениться в любой момент. Вот почему Кристофер ссылается на рекомендацию API, и я полностью согласен. В то же время, вы можете попытаться сделать это более надежным, вызвав его в cmd /U (но мое понимание того, что это делает или гарантирует, в лучшем случае нечетко), или попробовав оригинальный способ, а затем с помощью спецификации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...