Guión
Me gustaría ver la salida de los comandos de powershell que se ejecutan dentro de un método de un objeto, de la misma manera los veo "en vivo/cuando están sucediendo" cuando no están dentro del objeto.
Ejemplos
Para ilustrar la diferencia no deseada, mostraré 2 scripts, el primero muestra la salida del comando, el segundo no. Ambos se ejecutan abriendo powershell, navegando a su directorio y ejecutando con./<scriptname>.ps1
- Considere
scriptA.ps1
con contenido:
lxrun /install /y
Lo que produce el resultado deseado de:
Warning: lxrun.exe is only used to configure the legacy Windows Subsystem for Linux distribution. Distributions can be installed by visiting the Windows Store: https://aka.ms/wslstore This will install Ubuntu on Windows, distributed by Canonical and licensed under its terms available here: https://aka.ms/uowterms The legacy Windows Subsystem for Linux distribution is already installed.
scriptB.ps1
con contenido:
# runs single command
Class Object{
runCommand(){
lxrun /install /y
}
}
# create object
[Object] $object = [Object]::new()
# execute command in method runCommand() of [Object] object
$object.runCommand()
Lo cual no muestra ningún resultado en absoluto.
Intentos
Todos los intentos se realizan dentro del siguiente script, en la línea:<command here>
# runs single command
Class Object{
runCommand(){
`<command here>`
}
}
- Línea:
Write-Output (lxrun /install /y)
Salida resultante: (sin salida)
- Línea:
Write-Host (lxrun /install /y)
Resultado resultante: contenido correcto, pero formato de texto legible perdido/cambiado:
W a r n i n g : l x r u n . e x e i s o n l y u s e d t o c o n f i g u r e t h e l e g a c y W i n d o w s S u b s y s t e m f o r L i n u x d i s t r i b u t i o n . D i s t r i b u t i o n s c a n b e i n s t a l l e d b y v i s i t i n g t h e W i n d o w s S t o r e : h t t p s : / / a k a . m s / w s l s t o r e T h i s w i l l i n s t a l l U b u n t u o n W i n d o w s , d i s t r i b u t e d b y C a n o n i c a l a n d l i c e n s e d u n d e r i t s t e r m s a v a i l a b l e h e r e : h t t p s : / / a k a . m s / u o w t e r m s T h e l e g a c y W i n d o w s S u b s y s t e m f o r L i n u x d i s t r i b u t i o n i s a l r e a d y i n s t a l l e d .
- Línea:
Write-Host (lxrun /install /y) | Out-Host
Salida resultante: igual que en el intento 2.
- Línea:
Write-Host (lxrun /install /y) | Out-Default
Salida resultante: igual que en el intento 2.
- Línea:
Write-Host (lxrun /install /y) | Out-String
Salida resultante: igual que en el intento 2
- Línea:
write-verbose (lxrun /install /y)
Salida resultante: (sin salida)
Write-Verbose : Cannot convert 'System.Object[]' to the type 'System.String' required by parameter 'Message'. Specified method is not supported. At F:\path to example script\example.ps1:30 char:23 + write-verbose (lxrun /install /y) + ~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidArgument: (:) [Write-Verbose], ParameterBindingException + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.WriteVerboseCommand
- Línea:
write-verbose (lxrun /install /y) -Verbose
Salida resultante: igual que en 6 (excepto cuando se incluye la línea en la que ocurre el error -Detallado)
- Línea:
(lxrun /install /y) | Write-Host
Resultado resultante: mejor legible pero aún no es el ni
o c o n f i g u r e t h e l e g a c y W i n d o w s S u b s y s t e m f o r L i n u x d i s t r i b u t i o n . D i s t r i b u t i o n s c a n b e i n s t a l l e d b y v i s i t i n g t h e W i n d o w s S t o r e : h t t p s : / / a k a . m s / w s l s t o r e T h i s w i l l i n s t a l l U b u n t u o n W i n d o w s , d i s t r i b u t e d b y C a n o n i c a l a n d l i c e n s e d u n d e r i t s t e r m s a v a i l a b l e h e r e : h t t p s : / / a k a . m s / u o w t e r m s T h e l e g a c y W i n d o w s S u b s y s t e m f o r L i n u x d i s t r i b u t i o n i s a l r e a d y i n s t a l l e d . ```
- Línea:
Write-Verbose -Message (lxrun /install /y)
Salida resultante:
Write-Verbose : Cannot convert 'System.Object[]' to the type 'System.String' required by parameter 'Message'. Specified method is not supported.
At G:/path to file\example.ps1:35 char:32
+ Write-Verbose -Message (lxrun /install /y)
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Write-Verbose], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.WriteVerboseCommand
- Línea:
Write-Verbose -Message lxrun /install /y
Salida resultante: igual que en el intento 9
- Línea:
Write-Verbose -Message (lxrun /install /y) -Verbose
Salida resultante: igual que en el intento 9 (excepto cuando se incluye la línea en la que se produce el error -Verbose)
- Residencia enla pregunta y las respuestas vinculadas en los comentarios, modifiqué el script a:
# runs single command
#[CmdletBinding(SupportsShouldProcess=$true)]
[CmdletBinding()]
Param()
Class Object{
runCommand(){
lxrun /install /y|Write-Verbose
}
}
# create object
[Object] $object = [Object]::new()
# execute command in method runCommand() of [Object] object
$object.runCommand()
que se llama con el parámetro -Verbose al ejecutarlo: ./example.ps1 -Verbose
. Devuelve un texto negro y amarillo:
VERBOSE: W a r n i n g : l x r u n . e x e i s o n l y u s e d t o >c o n f i g u r e t h e l e g a c y W i n d o w s S u b s y s t e m f o r L i n u x d i s t >r i b u t i o n . VERBOSE: VERBOSE: VERBOSE: D i s t r i b u t i o n s c a n b e i n s t a l l e d b y v >i s i t i n g t h e W i n d o w s S t o r e : VERBOSE: VERBOSE: VERBOSE: h t t p s : / / a k a . m s / w s l s t o r e VERBOSE: VERBOSE: VERBOSE: VERBOSE: VERBOSE: VERBOSE: T h i s w i l l i n s t a l l U b u n t u o n W i n d o w s >, d i s t r i b u t e d b y C a n o n i c a l a n d l i c e n s e d u n d e r i t s t e r >m s a v a i l a b l e h e r e : VERBOSE: VERBOSE: VERBOSE: h t t p s : / / a k a . m s / u o w t e r m s VERBOSE: VERBOSE: VERBOSE: VERBOSE: VERBOSE: VERBOSE: T h e l e g a c y W i n d o w s S u b s y s t e m f o r L i >n u x d i s t r i b u t i o n i s a l r e a d y i n s t a l l e d . VERBOSE: VERBOSE: VERBOSE:
¿Dónde, por lo que entendí, Param()
se incluye para pasar/absorber el -Verbose
argumento, y el[CmdletBinding()]
permite let vincular la forma en que cmdlet
lo hace a, en lugar de la forma "normal" que lo hace un script.Todavía necesito entender cuál es/significa esa diferencia. Y el formato aún no es correcto/deseado con esta implementación de escritura detallada.
Pregunta
¿Cómo escribo la salida de un comando en el terminal PowerShell sin demora, sin perder su formato original (como con scriptA.ps1
)?
Nota
Se podría crear un analizador, pero creo que podría haber soluciones más eficientes y rápidas que aún no he encontrado.
Respuesta1
Al final resultó que escribir un analizador era una solución más rápida (en cuanto a construcción, no [necesariamente] en cuanto a tiempo de ejecución), ya que mi procedimiento de búsqueda no investigó (todavía) por qué y cómo los comandos con write..
etc. cambiaron la salida ( formato).
# runs single command
Class Object{
runCommand(){
$output = (lxrun /install /y)
Write-Host $this.parseOutput($output) # return formating back to "normal"
}
# removes null characters and then replaces triple spaces with enters.
[String] parseOutput([String] $output){
# first remove all nulls
$output = $output.Replace(([char]0).ToString(),'')
# then replace all triple occurrences of spaces with newlines
$output = $output.Replace(([char]32+[char]32+[char]32).ToString(),"`n")
return $output
}
}
# create object
[Object] $object = [Object]::new()
# execute command in method runCommand() of [Object] object
$object.runCommand()
Esto "resuelve"/soluciona el problema, pero prefiero una comprensión más profunda. Por lo tanto, si alguien puede explicarlo:
- Por qué se agregan caracteres adicionales
null
yspace
cuando se ejecuta un comando desde/en un objeto, lo agradecería mucho. - Cómo se puede hacer en la misma línea que el comando, sin llamar a un método escrito por uno mismo, se encuentra una mejor solución.