В захваченном выводе команды cmd.exe отсутствует последняя новая строка

Я пытаюсь вызвать встроенную команду cmd, такую ​​как echo в PowerShell, с помощью Invoke-Expression и преобразовать ее в массив байтов, но в выводе команды отсутствуют символы новой строки.

Пример:

([Text.Encoding]::ASCII).GetBytes((iex "cmd /c echo."))

Он ничего не возвращает вместо последовательности новой строки (CRLF).

Пожалуйста, сделайте шаг назад и опишите реальную проблему, которую вы пытаетесь решить, а не то, что вы считаете решением. Почему вы пытаетесь получить последовательность байтов новой строки, запустив echo через Invoke-Expression вместо, скажем, [Text.Encoding]::ASCII.GetBytes([Environment]::NewLine) или просто [byte[]](13,10)?

Ansgar Wiechers 03.02.2019 11:30
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
624
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я нашел решение. Не идеально, но я запишу вывод в файл, прочитаю его с помощью [System.IO.File]::ReadAllBytes("path_to_the_file"). и сохранить в переменную

Ответ принят как подходящий

тл;др:

PS> ([text.encoding]::ASCII).GetBytes(((cmd /c echo.) -join "`r`n") + "`r`n")
13
10

As an aside: iex (Invoke-Expression) should be avoided .

Прочтите справочную информацию и предостережения.


Когда PowerShell захватывает вывод stdout из внешней программы, такой как cmd.exe, он возвращает множество выхода линии с завершающей последовательностью новой строки подстриженный от каждого.

В качестве отступления: именно кодировка символов, о котором сообщает [console]::OutputEncoding, определяет, как PowerShell интерпретирует вывод, который в Windows PowerShell по умолчанию соответствует кодовой странице OEM устаревшей системной локали, и, на момент написания этой статьи, также — все еще — в PowerShell Core в Windows, хотя это надеюсь скоро изменится, учитывая, что PowerShell Core в противном случае использует (без спецификации) UTF-8 в качестве кодировки по умолчанию.

В вашем случае cmd /c echo. сгенерировал одну последовательность новой строки Windows, CRLF, которая в терминах PowerShell равна "`r`n" (вы также можете использовать [Environment]::NewLine для получения строки новой строки, соответствующей платформе).

PowerShell интерпретирует это как одну пустую строку, и из-за того, что в элементы массива не включена завершающая новая строка, а PowerShell разворачивает массив из одного элемента, вы получаете '', то есть пустой строки — вот почему вызов ([text.encoding]::ASCII).GetBytes() не произвел вывод.

Вы можете собрать массив строк вывода, созданный PowerShell, в одну многострочную строку вывода:

  • объединение элементов массива с новой строкой (-join "`r`n")
  • добавление последней завершающей новой строки (+ "`r`n")

как показано выше.

Предостережения: это "повторная сборка" делает два предположения, которое не всегда может быть правдой:

  • Что внешняя программа действительно выдавала последовательности Windows CRLF, а не только символы UNIX LF.

    • Однако на практике это различие редко имеет значение в PowerShell, поскольку он принимает обе формы новой строки взаимозаменяемо.
  • Что внешняя программа действительно сгенерировала новую строку тянущийся, что обычно, но не обязательно верно.

Если эти предположения проблематичны, перенаправление вывода в файл и чтение тот — как и в твой собственный ответ — являются правильным решением.

Предостережение: > в Windows PowerShell по умолчанию создает файлы UTF-16LE (а также неизменно добавляет новую строку), поэтому вы не получите байтов ASCII; поэтому используйте перенаправление свояcmd для создания файла (который будет использовать устаревшую OEM-кодировку, указанную chcp, которая обычно представляет собой суперсет ASCII):

  # Note that the `>` is *inside the quoted string* to ensure that it is
  # cmd.exe that interprets it.
  # (...) around `echo.` ensures that the space before `>` doesn't become
  # part of the output.
  PS> cmd /c '(echo.) >out.txt'; [IO.File]::ReadAllBytes("$PWD\out.txt")
  13
  10

Другие вопросы по теме

Похожие вопросы