Как вывести что-то в PowerShell

Я запускаю PowerShell script из пакетного файла. script извлекает веб-страницу и проверяет, является ли содержимое страницы строкой "ОК".

PowerShell script возвращает уровень ошибок пакету script.

Пакет script выполняется программой ScriptFTP, программой автоматизации FTP. Если возникает ошибка, я могу заставить ScriptFTP отправлять полный консольный вывод администратору через E-Mail.

В PowerShell script я хотел бы выводить возвращаемое значение с веб-сайта, если оно не является "ОК", поэтому сообщение об ошибке включается в вывод консоли и, таким образом, в почте статуса.

Я новичок в PowerShell и не знаю, какую функцию вывода использовать для этого. Я вижу три:

  • Write-Host
  • Write-Output
  • Write-Error

Каким будет правильное использование для записи в эквивалент Windows stdout?

Ответ 1

Простое выведение чего-то - PowerShell - вещь красоты - и одна из ее самых сильных сторон. Например, общий Hello, World! приложение сводится к одной строке:

"Hello, World!"

Он создает строковый объект, назначает вышеупомянутое значение и является последним элементом в конвейере команд, который вызывает метод .toString() и выводит результат на STDOUT (по умолчанию). Вещь красоты.

Другие команды Write-* специфичны для вывода текста в связанные потоки и имеют свое место как таковое.

Ответ 2

Думаю, в этом случае вам понадобится Write-Output.

Если у вас есть script как

Write-Output "test1";
Write-Host "test2";
"test3";

то, если вы вызываете script с перенаправленным выходом, что-то вроде yourscript.ps1 > out.txt, вы получите test2 на экране test1\ntest3\n в "out.txt".

Обратите внимание, что "test3" и строка Write-Output всегда добавят новую строку к вашему тексту, и в PowerShell нет способа остановить это (т.е. echo -n невозможно в PowerShell с помощью собственных команд). Если вы хотите (несколько базовую и легкую в Bash) функциональность echo -n, то см. ответ samthebest.

Если командный файл запускает команду PowerShell, он, скорее всего, захватит команду Write-Output. У меня были "длительные дискуссии" с системными администраторами о том, что должно быть написано на консоли, а что нет. Мы теперь согласились, что единственная информация, если script выполнена успешно или умерла, должна быть Write-Host 'ed, и все, что является script автором, возможно, должно знать о выполнении (какие элементы были обновлены, какие поля были установлены, и так далее) переходит к Write-Output. Таким образом, когда вы отправляете script системному администратору, он может легко runthescript.ps1 >someredirectedoutput.txt и видеть на экране, если все в порядке. Затем отправьте "someredirectedoutput.txt" обратно разработчикам.

Ответ 3

Я думаю, что следующее - хорошая выставка Эха против Write-Host. Обратите внимание, как test() на самом деле возвращает массив целых чисел, а не единственное целое число, как можно легко поверить.

function test {
    Write-Host 123
    echo 456 # AKA 'Write-Output'
    return 789
}

$x = test

Write-Host "x of type '$($x.GetType().name)' = $x"

Write-Host "'$x[0] = $($x[0])"
Write-Host "'$x[1] = $($x[1])"

Терминал вышеупомянутого:

123
x of type 'Object[]' = 456 789
$x[0] = 456
$x[1] = 789

Ответ 4

Вы можете использовать любой из них в своем сценарии, поскольку они пишут потоки по умолчанию (вывод и ошибка). Если вы отправляете вывод на другой командный файл, вы хотели бы использовать "Write-Output" , который в конечном итоге завершится в Write-Host.

В этой статье описываются различные параметры вывода: PowerShell O для вывода

Ответ 5

Вы просто не можете заставить PowerShell пропускать эти надоедливые символы перевода. Это не делает script или командлет.

Конечно, Write-Host - это абсолютная бессмыслица, потому что вы не можете перенаправлять/трубить с нее! Вам просто нужно написать свой собственный:

using System;

namespace WriteToStdout
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args != null)
            {
                Console.Write(string.Join(" ", args));
            }
        }
    }
}

например.

PS C:\> writetostdout finally I can write to stdout like echo -n
finally I can write to stdout like echo -nPS C:\>

Ответ 6

Write-Host "Found file - " + $File.FullName -ForegroundColor Magenta

Magenta может быть одним из значений счетчика "System.ConsoleColor" - Black, DarkBlue, DarkGreen, DarkCyan, DarkRed, DarkMagenta, DarkYellow, Gray, DarkGray, Blue, Green, Cyan, Red, Magenta, Yellow, White.

+ $File.FullName является необязательным и показывает, как поместить переменную в строку.

Ответ 7

  Что было бы правильно использовать для записи в Windows эквивалента стандартного вывода?

По сути, но, к сожалению, и Windows PowerShell, и PowerShell Core начиная с v7.0 отправляют все свои 6 (!) выходных потоков на стандартный вывод, когда вызывается извне, через PowerShell CLI.

  • См. эту проблему GitHub для обсуждения этого проблемного поведения, которое, скорее всего, не будет исправлено ради обратной совместимости.

  • На практике это означает, что любой поток PowerShell, в который вы отправляете выходные данные, будет воспринят внешним абонентом как вывод stdout:

    • Например, если вы выполните следующее из cmd.exe, вы не увидите выходных данных, потому что перенаправление stdout на NUL в равной степени относится ко всем потокам PowerShell:

      • C:\>powershell -noprofile -command "Write-Error error!" >NUL
    • Однако - что любопытно - если вы перенаправляете stderr, PowerShell отправляет свой поток ошибок на stderr, так что с помощью 2> вы можете выборочно перехватывать выходные данные потока ошибок; следующие выходные данные просто 'hi' - вывод потока успеха - при захвате вывода потока ошибок в файл err.txt:

      • C:\>powershell -noprofile -command "'hi'; Write-Error error!" 2>err.txt

желаемое поведение :

  • Отправьте PowerShell успешный выходной поток (номер 1) на стандартный вывод.
  • Отправлять выходные данные из всех других потоков в stderr, который является единственной опцией, учитывая, что между процессами существует только 2 выходных потока: stdout (стандартный вывод) для данных и stderr (стандартная ошибка) для сообщений об ошибках и все другие типы сообщений - например, информация о состоянии - которые не являются данными.

  • Желательно сделать это различие в вашем коде, даже если в настоящее время оно не соблюдается.


Внутри PowerShell:

  • Write-Host - это для вывода на дисплей, и обходит поток вывода успешных результатов - поэтому его вывод нельзя ни (непосредственно) захватить в переменной, ни подавить, ни перенаправить.

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

    • Из-за предыдущей невозможности захвата или перенаправления PowerShell версии 5 сделал Write-Host вновь введенным информационным потоком (номер 6), поэтому с тех пор можно захватывать и перенаправлять вывод Write-Host.

  • Write-Error предназначен для записи нескончаемых ошибок в поток ошибок (номер 2); концептуально поток ошибок является эквивалентом stderr.

  • Write-Output пишет в поток success [output] (число 1), что концептуально эквивалентно stdout; это поток для записи данных (результатов) в.

    • Однако явное использование Write-Output редко требуется из-за функции неявного вывода PowerShell:
      • Вывод любой команды или выражения, которые явно не захвачены, не подавлены и не перенаправлены, автоматически отправляются в поток успеха; например, Write-Output "Honey, I'm $HOME" и "Honey, I'm $HOME" эквивалентны, причем последние не только более краткие, но и более быстрые.

Ответ 8

Используйте внешнюю программу, как изнутри PowerShell script:

cmd /c echo "Long string: $LongStr" 

Это глупо и дорого с точки зрения запуска отдельного процесса, но PowerShell плохо разработан.