it-swarm.com.de

Wie gebe ich Text ohne Zeilenumbruch in PowerShell aus?

Ich möchte, dass mein PowerShell-Skript etwa Folgendes druckt:

Enabling feature XYZ......Done

Das Skript sieht ungefähr so ​​aus:

Write-Output "Enabling feature XYZ......."
Enable-SPFeature...
Write-Output "Done"

Aber Write-Output druckt am Ende immer eine neue Zeile, sodass meine Ausgabe nicht in einer Zeile steht. Gibt es eine Möglichkeit, dies zu tun?

115
Amit G

 Write-Host -NoNewline "Aktivierungsfunktion XYZ ......." 

134
Shay Levy

Leider, wie in mehreren Antworten und Kommentaren vermerkt, Write-Host kann gefährlich sein und nicht an andere Prozesse weitergeleitet werden und Write-Output hat nicht den -NoNewline Flagge.

Aber diese Methoden sind die "* nix" -Methoden, um den Fortschritt anzuzeigen, und die "PowerShell" -Methode, um dies zu tun, scheint Write-Progress: Am oberen Rand des PowerShell-Fensters wird eine Leiste mit Fortschrittsinformationen angezeigt, die ab PowerShell 3.0 verfügbar sind. Weitere Informationen finden Sie im Handbuch .

# 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"

Und um das Beispiel des OP zu nehmen:

# 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"
36
Thomas

Obwohl es in Ihrem Fall möglicherweise nicht funktioniert (da Sie dem Benutzer informative Ausgaben bereitstellen), erstellen Sie eine Zeichenfolge, mit der Sie die Ausgabe anhängen können. Wenn es Zeit für die Ausgabe ist, geben Sie einfach die Zeichenfolge aus.

Natürlich ignorieren Sie, dass dieses Beispiel in Ihrem Fall dumm ist, aber im Konzept nützlich ist:

$output = "Enabling feature XYZ......."
Enable-SPFeature...
$output += "Done"
Write-Output $output

Zeigt: 

Enabling feature XYZ.......Done
13
shufler

Ja, da andere Antworten Zustände haben, kann dies nicht mit Write-Output erfolgen. Wenn PowerShell ausfällt, wenden Sie sich an .NET. Hier gibt es sogar einige .NET-Antworten, die jedoch komplexer sind, als sie sein müssen.

Benutz einfach:

[Console]::Write("Enabling feature XYZ.......")
Enable-SPFeature...
Write-Output "Done"

Es ist keine reinste PowerShell, aber es funktioniert.

4
Mark Travis

Das Problem, das ich traf, bestand darin, dass Write-Output die Ausgabe bei der Verwendung von PowerShell v2 (zumindest in stdout) tatsächlich zu Zeilenumbrüchen führt. Ich habe versucht, einen XML-Text ohne Erfolg in stdout zu schreiben, da er bei Zeichen 80 schwer umschlossen sein würde.

Die Problemumgehung war zu verwenden

[Console]::Out.Write($myVeryLongXMLTextBlobLine)

Dies war in PowerShell v3 kein Problem. Write-Output scheint dort richtig zu funktionieren.

Je nachdem, wie das PowerShell-Skript aufgerufen wird, müssen Sie es möglicherweise verwenden

[Console]::BufferWidth =< length of string, e.g. 10000)

bevor du an stdout schreibst.

2
eythort

In PowerShell scheint dies nicht möglich zu sein. Alle vorherigen Antworten sind nicht korrekt, weil sie sich nicht wie Write-Output verhalten, sondern eher wie Write-Host, bei dem dieses Problem ohnehin nicht auftritt.

Die schließende Lösung scheint Write-Host mit dem -NoNewLine-Parameter zu verwenden. Sie können dies nicht generieren, was im Allgemeinen ein Problem ist, aber es gibt eine Möglichkeit, diese Funktion zu überschreiben, wie in Write-Host => Export in eine Datei beschrieben, sodass Sie den Parameter problemlos akzeptieren können für eine Ausgabedatei. Dies ist noch lange keine gute Lösung. Mit Start-Transcript ist dies nützlicher, das Cmdlet hat jedoch Probleme mit nativen Anwendungen.

Write-Outputs kann einfach nicht das tun, was Sie in einem allgemeinen Kontext benötigen.

2
majkinetor

Um in eine Datei zu schreiben, können Sie ein Byte-Array verwenden. Im folgenden Beispiel wird eine leere Zip-Datei erstellt, zu der Sie Dateien hinzufügen können:

[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)

Oder benutze:

[Byte[]] $text = [System.Text.Encoding]::UTF8.getBytes("Enabling feature XYZ.......")
[System.IO.File]::WriteAllBytes("C:\My.Zip", $text)
2
FrinkTheBrave

Die Antwort von Shufler ist richtig. Anders ausgedrückt: Anstatt die Werte mit ARRAY FORM an Write-Output zu übergeben,

Write-Output "Parameters are:" $Year $Month $Day

oder das Äquivalent bei mehreren Aufrufen von Write-Output,

Write-Output "Parameters are:"
Write-Output $Year
Write-Output $Month
Write-Output $Day
Write-Output "Done."

verketten Sie Ihre Komponenten zunächst zu einem STRING VARIABLE:

$msg="Parameters are: $Year $Month $Day"
Write-Output $msg

Dadurch werden die Zwischen-CRLFs durch mehrmaliges Aufrufen von Write-Output (oder ARRAY FORM) verhindert, die endgültige CRLF des Write-Output-Commandlets wird jedoch nicht unterdrückt. Dazu müssen Sie ein eigenes Commandlet schreiben, eine der anderen hier aufgeführten verwobenen Problemumgehungen verwenden oder warten, bis Microsoft die -NoNewline-Option für Write-Output unterstützt.

Ihr Wunsch, der Konsole eine Textfortschrittsanzeige (d. H. "....") zur Verfügung zu stellen, anstatt in eine Protokolldatei zu schreiben, sollte auch durch die Verwendung von Write-Host erfüllt werden. Sie können beides erreichen, indem Sie den msg-Text in einer Variablen sammeln, um in das Protokoll zu schreiben, und Write-Host verwenden, um der Konsole einen Fortschritt zu ermöglichen. Diese Funktionalität kann in Ihrem eigenen Commandlet zur bestmöglichen Wiederverwendung von Code kombiniert werden.

2
David Rudd

Eine Vereinfachung der Antwort von FrinkTheBrave:

[System.IO.File]::WriteAllText("c:\temp\myFile.txt", $myContent)
1
Russell Speight

Sie können PowerShell einfach nicht dazu bringen, diese lästigen Zeilenumbrüche wegzulassen ... Es gibt kein Skript oder Cmdlet, das dies tut. Natürlich ist Write-Host absoluter Blödsinn, weil Sie nicht weiterleiten/pipen können!

Sie können jedoch Ihre eigene EXE-Datei schreiben, um dies zu tun. Dies wurde in Stack Overflow-Frage Ausgabe von etwas in PowerShell erläutert.

1
samthebest

Write-Host ist schrecklich, ein Zerstörer von Welten, aber Sie können es nur verwenden, um einem Benutzer den Fortschritt anzuzeigen, während Sie Write-Output zum Protokollieren verwenden (nicht, dass das OP zum Protokollieren aufgefordert wurde).

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's doing if ($result -ne $null) { Write-Host "complete" } else { Write-Host "failed" }

1

Im Folgenden wird der Cursor an den Anfang der vorherigen Zeile gesetzt. Sie müssen es in die richtige horizontale Position bringen (mit $ pos.X, um es seitlich zu verschieben):

$pos = $Host.ui.RawUI.get_cursorPosition()
$pos.Y -= 1
$Host.UI.RawUI.set_cursorPosition($Pos)

Ihre aktuelle Ausgabe ist 27 Felder mehr, also $ pos.X = 27 könnte funktionieren.

0
Will Martin

Es ist zwar nicht besonders elegant, macht aber genau das, was OP angefordert hat. Beachten Sie, dass sich die ISE mit StdOut beschäftigt, so dass keine Ausgabe erfolgt. Damit dieses Skript funktioniert, kann es nicht in der ISE ausgeführt werden.

$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()

Ich habe geschummelt, aber ich glaube, dies ist die einzige Antwort, die alle Anforderungen erfüllt. Dies vermeidet nämlich das nachgestellte CRLF, stellt einen Platz bereit, an dem der andere Vorgang in der Zwischenzeit abgeschlossen werden kann, und leitet nach Bedarf ordnungsgemäß zu stdout weiter.

$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.'
0
durette