web-dev-qa-db-fra.com

Comment puis-je générer du texte sans nouvelle ligne dans PowerShell?

Je veux que mon script PowerShell imprime quelque chose comme ceci:

Enabling feature XYZ......Done

Le script ressemble à ceci:

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

Mais Write-Output imprime toujours une nouvelle ligne à la fin afin que ma sortie ne soit pas sur une ligne. Y a-t-il un moyen de faire cela?

115
Amit G

 Write-Host -NoNewline "Activation de la fonction XYZ ......." 

134
Shay Levy

Malheureusement, comme indiqué dans plusieurs réponses et commentaires, Write-Host peut être dangereux et ne peut pas être acheminé vers d'autres processus et Write-Output ne possède pas l'indicateur -NoNewline.

Mais ces méthodes sont les méthodes "* nix" pour afficher la progression, la méthode "PowerShell" semble être Write-Progress: elle affiche une barre en haut de la fenêtre PowerShell avec les informations de progression disponibles à partir de PowerShell 3.0, voir manuel pour plus de détails.

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

Et pour prendre l'exemple du PO:

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

Bien que cela puisse ne pas fonctionner dans votre cas (puisque vous fournissez une sortie informative à l'utilisateur), créez une chaîne que vous pouvez utiliser pour ajouter la sortie. Quand il est temps de le sortir, il suffit de sortir la chaîne.

Ignorer bien sûr que cet exemple est stupide dans votre cas mais utile dans le concept:

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

Affiche: 

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

Oui, comme d'autres réponses ont des états, cela ne peut pas être fait avec Write-Output. Si PowerShell échoue, faites appel à .NET. Il existe même quelques réponses .NET ici, mais elles sont plus complexes que nécessaire.

Il suffit d'utiliser:

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

Ce n’est pas le plus pur PowerShell, mais cela fonctionne.

4
Mark Travis

Le problème que j'ai rencontré est que Write-Output coupe la sortie lorsque vous utilisez PowerShell v2, du moins sur stdout. J'essayais d'écrire un texte XML sur stdout sans succès, car il serait durement encapsulé au caractère 80.

La solution de contournement était d'utiliser

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

Ce n'était pas un problème dans PowerShell v3. Write-Output semble fonctionner correctement là-bas.

Selon la manière dont le script PowerShell est appelé, vous devrez peut-être utiliser

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

avant d'écrire sur stdout.

2
eythort

Il semble n'y avoir aucun moyen de faire cela dans PowerShell. Toutes les réponses précédentes ne sont pas correctes, car elles ne se comportent pas de la même manière que Write-Output mais plutôt Write-Host qui n'a de toute façon pas ce problème.

La solution de fermeture semble utiliser Write-Host avec le paramètre -NoNewLine. Vous ne pouvez pas diriger ce qui pose problème, mais il existe un moyen de remplacer cette fonction comme décrit dans Write-Host => Exporter vers un fichier, de sorte que vous puissiez facilement lui faire accepter le paramètre. pour un fichier de sortie. C'est encore loin d'être une bonne solution. Avec Start-Transcript, cela est plus utilisable, mais cette applet de commande a des problèmes avec les applications natives.

Write-Outputsimplement ne peut pas faire ce dont vous avez besoin dans un contexte général.

2
majkinetor

Pour écrire dans un fichier, vous pouvez utiliser un tableau d'octets. L'exemple suivant crée un fichier Zip vide, auquel vous pouvez ajouter des fichiers:

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

Ou utiliser:

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

La réponse de shufler est correcte. En d'autres termes: au lieu de transmettre les valeurs à Write-Output à l'aide de ARRAY FORM,

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

ou l'équivalent par plusieurs appels à Write-Output,

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

concaténez vos composants dans un STRING VARIABLE en premier:

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

Cela évitera les CRLF intermédiaires causés par l'appel de plusieurs fois en écriture-sortie (ou ARRAY FORM), mais ne supprimera bien entendu pas le CRLF final du commandlet d'écriture-sortie. Pour cela, vous devrez écrire votre propre commandlet, utiliser l’une des solutions de contournement énumérées ici ou attendre que Microsoft décide de prendre en charge l’option -NoNewline pour Write-Output.

Votre désir de fournir un indicateur de progression textuel à la console (c'est-à-dire "....") au lieu d'écrire dans un fichier journal doit également être satisfait en utilisant Write-Host. Pour ce faire, vous pouvez collecter le texte du message dans une variable à écrire dans le journal ET à l'aide de Write-Host pour indiquer la progression à la console. Cette fonctionnalité peut être combinée dans votre propre commandlet pour une réutilisation optimale du code.

2
David Rudd

Une simplification de la réponse de FrinkTheBrave:

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

Vous ne pouvez tout simplement pas faire en sorte que PowerShell omette ces nouvelles lignes embêtantes ... Il n’ya pas de script ou d’applet de commande à cette fin. Bien sûr, Write-Host est un non-sens absolu, car vous ne pouvez pas le rediriger/le diriger!

Néanmoins, vous pouvez écrire votre propre fichier EXE pour le faire. C’est ce que j’ai expliqué à la question Stool Overflow Comment afficher quelque chose dans PowerShell.

1
samthebest

Write-Host est terrible, détruit des mondes, mais vous pouvez l'utiliser uniquement pour afficher la progression d'un utilisateur tout en utilisant Write-Output pour vous connecter (même si le PO n'a pas demandé de consignation).

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
ATtheincredibleaf

Ce qui suit replacera le curseur au début de la ligne précédente. C'est à vous de le placer dans la bonne position horizontale (avec $ pos.X pour le déplacer latéralement):

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

Votre sortie actuelle est de 27 espaces, donc $ pos.X = 27 pourrait fonctionner.

0
Will Martin

Ce n'est peut-être pas très élégant, mais il fait exactement ce que l'OP a demandé. Notez que l'ISE dérange avec StdOut, donc il n'y aura pas de sortie. Pour que ce script fonctionne, il ne peut pas être exécuté dans 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()

J'ai triché, mais je crois que c'est la seule réponse qui répond à toutes les exigences. Cela évite notamment le CRLF de fin, fournit un emplacement à l'autre pour terminer l'opération et redirige correctement vers stdout si nécessaire.

$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