script - powershell tutorial
¿Cómo puedo enviar texto sin una nueva línea en PowerShell? (14)
Desafortunadamente, como se señala en varias respuestas y comentarios, Write-Host
puede ser peligroso y no se puede canalizar a otros procesos y Write-Output
no tiene el -NoNewline
.
Pero esos métodos son las formas "* nix" de mostrar la progresión, la forma de "PowerShell" para hacer eso parece ser Write-Progress
: muestra una barra en la parte superior de la ventana de PowerShell con información de progreso, disponible desde PowerShell 3.0 en adelante, ver el manual para más detalles.
# 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"
Y para tomar el ejemplo de OP:
$output = "Enabling feature XYZ......."
Enable-SPFeature...
$output += "Done"
Write-Output $output
Quiero que mi script de PowerShell imprima algo como esto:
Enabling feature XYZ......Done
El script se ve así:
Write-Output "Enabling feature XYZ......."
Enable-SPFeature...
Write-Output "Done"
Pero Write-Output
siempre imprime una nueva línea al final, por lo que mi salida no está en una línea. ¿Hay alguna forma de hacer esto?
El problema que acerté fue que Write-Output en realidad salta la salida cuando se usa con PowerShell v2, al menos para stdout. Intentaba escribir un texto XML en stdout sin éxito, porque sería difícil para el personaje 80.
La solución fue usar
[Console]::BufferWidth =< length of string, e.g. 10000)
Esto no fue un problema en PowerShell v3. Write-Output parece estar funcionando correctamente allí.
Según cómo se invoque el script de PowerShell, es posible que deba usar
Write-Output "Parameters are:" $Year $Month $Day
antes de escribir en stdout.
La respuesta por shufler es correcta. Dicho de otra manera: en lugar de pasar los valores a Write-Output usando el ARRAY FORM,
Write-Output "Parameters are:"
Write-Output $Year
Write-Output $Month
Write-Output $Day
Write-Output "Done."
o el equivalente por múltiples llamadas a Write-Output,
$msg="Parameters are: $Year $Month $Day"
Write-Output $msg
Concatene sus componentes en una VARIABLE DE CADENA primero:
[System.IO.File]::WriteAllText("c:/temp/myFile.txt", $myContent)
Esto evitará los CRLF intermedios causados por la invocación de Write-Output varias veces (o ARRAY FORM), pero por supuesto no suprimirá el CRLF final del comando Write-Output. Para eso, tendrá que escribir su propio comando, usar una de las otras soluciones complejas enumeradas aquí, o esperar hasta que Microsoft decida admitir la opción -NoNewline
para Write-Output.
Su deseo de proporcionar un medidor de progreso textual a la consola (es decir, "....") en lugar de escribir en un archivo de registro, también debe cumplirse mediante el uso de Write-Host. Puede lograr ambos recopilando el texto del mensaje en una variable para escribir en el registro Y usando el Anfitrión-Anfitrión para proporcionar progreso a la consola. Esta funcionalidad se puede combinar en su propio programa para una mayor reutilización del código.
Lo siguiente colocará el cursor al principio de la fila anterior. Depende de usted colocarlo en la posición horizontal correcta (usando $ pos.X para moverlo hacia los lados):
$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()
Su salida actual es de 27 espacios, por lo que $ pos.X = 27 podría funcionar.
Para escribir en un archivo puede usar una matriz de bytes. El siguiente ejemplo crea un archivo ZIP vacío, al que puede agregar archivos:
[Byte[]] $text = [System.Text.Encoding]::UTF8.getBytes("Enabling feature XYZ.......")
[System.IO.File]::WriteAllBytes("C:/My.zip", $text)
O usar:
[Console]::Out.Write($myVeryLongXMLTextBlobLine)
Parece que no hay forma de hacer esto en PowerShell. Todas las respuestas anteriores no son correctas, porque no se comportan de la misma manera que se comporta Write-Output
sino más bien como Write-Host
que de todos modos no tiene este problema.
La solución de cierre parece usar Write-Host
con el parámetro -NoNewLine
. No puede canalizar esto, que es un problema en general, pero hay una manera de anular esta función como se describe en Write-Host => Exportar a un archivo , por lo que puede hacer que acepte fácilmente el parámetro para un archivo de salida. Esto todavía está lejos de ser una buena solución. Con Start-Transcript
esto es más útil, pero ese cmdlet tiene problemas con las aplicaciones nativas.
Write-Output
simplemente no puede hacer lo que necesita en un contexto general.
Puede que no sea terriblemente elegante, pero hace exactamente lo que OP solicitó. Tenga en cuenta que el ISE entra en conflicto con StdOut, por lo que no habrá salida. Para ver funcionar este script, no se puede ejecutar dentro del 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()
Sí, como otras respuestas tienen estados, no se puede hacer con Write-Output. Cuando PowerShell falla, vaya a .NET, hay incluso un par de respuestas de .NET aquí, pero son más complejas de lo que deberían ser.
Solo usa:
[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)
No es el PowerShell más puro, pero funciona.
Si bien es posible que no funcione en su caso (dado que proporciona resultados informativos para el usuario), cree una cadena que pueda usar para agregar resultados. Cuando llega el momento de emitirlo, solo da salida a la cadena.
Ignorando, por supuesto, que este ejemplo es tonto en su caso pero útil en concepto:
Enabling feature XYZ.......Done
Muestra:
[Console]::Write("Enabling feature XYZ.......")
Enable-SPFeature...
Write-Output "Done"
Simplemente no puede hacer que PowerShell omita esas nuevas líneas molestas ... No hay script o cmdlet que lo haga. Por supuesto, Write-Host es una absoluta tontería, ¡porque no puedes redirigir / canalizar desde allí!
Sin embargo, puede escribir su propio archivo EXE para hacerlo, que es lo que le expliqué cómo hacer en pregunta cómo generar algo en PowerShell .
Una simplificación para la respuesta de FrinkTheBrave:
$pos = $host.ui.RawUI.get_cursorPosition()
$pos.Y -= 1
$host.UI.RawUI.set_cursorPosition($Pos)
Usted puede hacer esto absolutamente. Write-Output tiene una bandera llamada " NoEnumerate " que es esencialmente la misma cosa.
Write-Host es terrible, un destructor de mundos, sin embargo, puede usarlo solo para mostrar el progreso a un usuario mientras usa Write-Output para iniciar sesión (no es que el OP solicite el registro).
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" }
# 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"