Ответ 1
Write-Host -NoNewline "Включение функции XYZ......."
Я хочу, чтобы мой PowerShell script напечатал что-то вроде этого:
Enabling feature XYZ......Done
script выглядит примерно так:
Write-Output "Enabling feature XYZ......."
Enable-SPFeature...
Write-Output "Done"
Но Write-Output
всегда печатает новую строку в конце, поэтому мой вывод не находится в одной строке. Есть ли способ сделать это?
Write-Host -NoNewline "Включение функции XYZ......."
К сожалению, как отмечено в нескольких ответах и комментариях, Write-Host
может быть опасным и не может быть передан в другие процессы, а Write-Output
не имеет флага -NoNewline
.
Но эти методы - это "* nix" способы отображения прогрессии, способ "PowerShell" для этого выглядит как Write-Progress
: он отображает панель в верхней части окна PowerShell с информацией о ходе работы, доступной из PowerShell 3.0, см. Руководство для деталей.
# Total time to sleep
$start_sleep = 120
# Time to sleep between each notification
$sleep_iteration = 30
Write-Output ( "Sleeping {0} seconds ... " -f ($start_sleep) )
for ($i=1 ; $i -le ([int]$start_sleep/$sleep_iteration) ; $i++) {
Start-Sleep -Seconds $sleep_iteration
Write-Progress -CurrentOperation ("Sleep {0}s" -f ($start_sleep)) ( " {0}s ..." -f ($i*$sleep_iteration) )
}
Write-Progress -CurrentOperation ("Sleep {0}s" -f ($start_sleep)) -Completed "Done waiting for X to finish"
И взять пример OP:
# For the file log
Write-Output "Enabling feature XYZ"
# For the operator
Write-Progress -CurrentOperation "EnablingFeatureXYZ" ( "Enabling feature XYZ ... " )
Enable-SPFeature...
# For the operator
Write-Progress -CurrentOperation "EnablingFeatureXYZ" ( "Enabling feature XYZ ... Done" )
# For the log file
Write-Output "Feature XYZ enabled"
Хотя это может не работать в вашем случае (поскольку вы предоставляете информационный результат пользователю), создайте строку, которую вы можете использовать для добавления вывода. Когда это время, чтобы вывести его, просто введите строку.
Игнорируя, конечно, что этот пример глуп в вашем случае, но полезен по понятию:
$output = "Enabling feature XYZ......."
Enable-SPFeature...
$output += "Done"
Write-Output $output
Отображает:
Enabling feature XYZ.......Done
Для записи в файл вы можете использовать массив байтов. В следующем примере создается пустой ZIP файл, который вы можете добавить в файл:
[Byte[]] $zipHeader = 80, 75, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
[System.IO.File]::WriteAllBytes("C:\My.zip", $zipHeader)
Или используйте:
[Byte[]] $text = [System.Text.Encoding]::UTF8.getBytes("Enabling feature XYZ.......")
[System.IO.File]::WriteAllBytes("C:\My.zip", $text)
Проблема, с которой я столкнулась, заключалась в том, что Write-Output фактически выводит строки на выходе при использовании PowerShell v2, по крайней мере, в stdout. Я пытался написать XML-текст в stdout без успеха, потому что это было бы сложно обернуть символом 80.
Обходной путь состоял в том, чтобы использовать
[Console]::Out.Write($myVeryLongXMLTextBlobLine)
Это не проблема в PowerShell v3. Кажется, что сработала запись-вывод.
В зависимости от того, как вызывается PowerShell script, вам может потребоваться использовать
[Console]::BufferWidth =< length of string, e.g. 10000)
прежде чем писать в стандартный вывод.
В PowerShell, похоже, нет способа сделать это. Все предыдущие ответы неверны, потому что они не ведут себя так, как ведет себя Write-Output
, но больше похоже на Write-Host
, который в любом случае не имеет этой проблемы.
Закрывающее решение, похоже, использует Write-Host
с параметром -NoNewLine
. Вы не можете передать это, что является проблемой в целом, но есть способ переопределить эту функцию, как описано в Write-Host = > Экспортировать в файл, чтобы вы могли легко принять параметр для выходного файла. Это еще далеко не хорошее решение. С Start-Transcript
это более удобно, но этот командлет имеет проблемы с собственными приложениями.
Write-Output
просто не может делать то, что вам нужно в общем контексте.
Да, поскольку другие ответы имеют состояния, это не может быть сделано с помощью Write-Output. В случае сбоя PowerShell, перейдите к .NET, есть даже несколько ответов .NET, но они сложнее, чем они должны быть.
Просто используйте:
[Console]::Write("Enabling feature XYZ.......")
Enable-SPFeature...
Write-Output "Done"
Это не самая чистая PowerShell, но она работает.
Write-Host ужасен, разрушитель миров, но вы можете использовать его только для отображения прогресса пользователя при использовании Write-Output для регистрации (не то, что ОП запрашивал запись в журнал).
Write-Output "Enabling feature XYZ" | Out-File "log.txt" # Pipe to log file Write-Host -NoNewLine "Enabling feature XYZ......." $result = Enable-SPFeature $result | Out-File "log.txt" # You could try{}catch{} an exception on Enable-SPFeature depending on what it doing if ($result -ne $null) { Write-Host "complete" } else { Write-Host "failed" }
Вы просто не можете заставить PowerShell опустить эти надоедливые символы перевода строки... Нет script или командлета. Конечно, Write-Host - абсолютная глупость, потому что вы не можете перенаправлять/трубить с нее!
Тем не менее, вы можете написать свой собственный EXE файл, чтобы сделать это, что я объяснил, как это сделать в вопросе Как вывести что-то в PowerShell.
Упрощение ответа FrinkTheBrave:
[System.IO.File]::WriteAllText("c:\temp\myFile.txt", $myContent)
Ответ shufler правильный. Иными словами: вместо передачи значений в Write-Output с использованием ФОРМЫ МАШИН,
Write-Output "Parameters are:" $Year $Month $Day
или эквивалент несколькими вызовами Write-Output,
Write-Output "Parameters are:"
Write-Output $Year
Write-Output $Month
Write-Output $Day
Write-Output "Done."
сначала соедините ваши компоненты с STRING VARIABLE:
$msg="Parameters are: $Year $Month $Day"
Write-Output $msg
Это предотвратит промежуточные CRLF, вызванные вызовом Write-Output несколько раз (или ARRAY FORM), но, конечно, не будет подавлять окончательный CRLF в командном файле Write-Output. Для этого вам нужно будет написать свой собственный комманд, использовать один из других запутанных обходных решений, перечисленных здесь, или дождаться, пока Microsoft решит поддержать параметр -NoNewline
для Write-Output.
Ваше желание предоставить текстовый индикатор прогресса на консоль (т.е. "...." ) в отличие от записи в файл журнала также должно быть удовлетворено с помощью Write-Host. Вы можете выполнить оба, собирая текст msg в переменную для записи в журнал AND, используя Write-Host, чтобы обеспечить прогресс в консоли. Эта функциональность может быть объединена в ваш собственный командный файл для лучшего повторного использования кода.
Следующее поместит курсор назад в начале предыдущей строки. Вам нужно разместить его в правильном горизонтальном положении (используя $pos.X, чтобы переместить его в сторону):
$pos = $host.ui.RawUI.get_cursorPosition()
$pos.Y -= 1
$host.UI.RawUI.set_cursorPosition($Pos)
Ваш текущий выход составляет 27 пробелов, поэтому $pos.X = 27 может работать.
Это может быть не очень элегантно, но это точно то, что запросил OP. Обратите внимание, что ISE работает с StdOut, поэтому выход не будет. Чтобы увидеть эту работу script, она не может быть запущена в ISE.
$stdout=[System.Console]::OpenStandardOutput()
$strOutput="Enabling feature XYZ... "
$stdout.Write(([System.Text.Encoding]::ASCII.GetBytes($strOutput)),0,$strOutput.Length)
Enable-SPFeature...
$strOutput="Done"
$stdout.Write(([System.Text.Encoding]::ASCII.GetBytes($strOutput)),0,$strOutput.Length)
$stdout.Close()
Я обманул, но я считаю, что это единственный ответ, который отвечает всем требованиям. А именно, это позволяет избежать конечного CRLF, предоставляет место для выполнения другой операции за это время и надлежащим образом перенаправляет на стандартный вывод при необходимости.
$c_sharp_source = @"
using System;
namespace StackOverflow
{
public class ConsoleOut
{
public static void Main(string[] args)
{
Console.Write(args[0]);
}
}
}
"@
$compiler_parameters = New-Object System.CodeDom.Compiler.CompilerParameters
$compiler_parameters.GenerateExecutable = $true
$compiler_parameters.OutputAssembly = "consoleout.exe"
Add-Type -TypeDefinition $c_sharp_source -Language CSharp -CompilerParameters $compiler_parameters
.\consoleout.exe "Enabling feature XYZ......."
Write-Output 'Done.'
Вы можете это сделать абсолютно. Write-Output имеет флаг под названием " NoEnumerate", который по сути является тем же самым.