Saltar al contenido

Write-Host vs Write-Information en PowerShell 5

Solución:

los Write-* Los cmdlets le permiten canalizar la salida de su código de PowerShell de una manera estructurada, por lo que puede distinguir fácilmente los mensajes de diferente gravedad entre sí.

  • Write-Host: muestra mensajes a un usuario interactivo en la consola. A diferencia del otro Write-* cmdlets este no es adecuado ni está diseñado para fines de automatización / redirección. No malvado, solo diferente.
  • Write-Output: escribe la salida “normal” del código en el flujo de salida predeterminado (correcto) (“STDOUT”).
  • Write-Error: escribe información de error en una secuencia separada (“STDERR”).
  • Write-Warning: escriba mensajes que considere advertencias (es decir, cosas que no son fallas, pero algo que el usuario debería tener en cuenta) en una secuencia separada.
  • Write-Verbose: escriba la información que considere más detallada que la salida “normal” en una secuencia separada.
  • Write-Debug: escriba la información que considere relevante para depurar su código en una secuencia separada.

Write-Information es solo una continuación de este enfoque. Le permite implementar niveles de registro en su salida (Debug, Verbose, Information, Warning, Error) y aún tener el flujo de salida exitoso disponible para la salida regular.

En cuanto a por qué Write-Host se convirtió en un envoltorio Write-Information: No sé el motivo real de esta decisión, pero sospecho que es porque la mayoría de la gente no entiende cómo Write-Host realmente funciona, es decir, para qué se puede utilizar y para qué no se debe utilizar.


Que yo sepa, no existe un enfoque generalmente aceptado o recomendado para iniciar sesión en PowerShell. Por ejemplo, podría implementar una función de registro única como @JeremyMontgomery sugirió en su respuesta:

function Write-Log {
  Param(
    [Parameter(Mandatory=$true, Position=0)]
    [ValidateNotNullOrEmpty()]
    [string]$Message,
    [Parameter(Mandatory=$false, Position=1)]
    [ValidateSet('Error', 'Warning', 'Information', 'Verbose', 'Debug')]
    [string]$LogLevel="Information"
  )

  switch ($LogLevel) {
    'Error'       { ... }
    'Warning'     { ... }
    'Information' { ... }
    'Verbose'     { ... }
    'Debug'       { ... }
    default       { throw "Invalid log level: $_" }
  }
}

Write-Log 'foo'                    # default log level: Information
Write-Log 'foo' 'Information'      # explicit log level: Information
Write-Log 'bar' 'Debug'

o un conjunto de funciones de registro (una para cada nivel de registro):

function Write-LogInformation {
  Param(
    [Parameter(Mandatory=$true, Position=0)]
    [ValidateNotNullOrEmpty()]
    [string]$Message
  )

  ...
}

function Write-LogDebug {
  Param(
    [Parameter(Mandatory=$true, Position=0)]
    [ValidateNotNullOrEmpty()]
    [string]$Message
  )

  ...
}

...

Write-LogInformation 'foo'
Write-LogDebug 'bar'

Otra opción es crear un objeto registrador personalizado:

$logger = New-Object -Type PSObject -Property @{
  Filename=""
  Console  = $true
}
$logger | Add-Member -Type ScriptMethod -Name Log -Value {
  Param(
    [Parameter(Mandatory=$true, Position=0)]
    [ValidateNotNullOrEmpty()]
    [string]$Message,
    [Parameter(Mandatory=$false, Position=1)]
    [ValidateSet('Error', 'Warning', 'Information', 'Verbose', 'Debug')]
    [string]$LogLevel="Information"
  )

  switch ($LogLevel) {
    'Error'       { ... }
    'Warning'     { ... }
    'Information' { ... }
    'Verbose'     { ... }
    'Debug'       { ... }
    default       { throw "Invalid log level: $_" }
  }
}
$logger | Add-Member -Type ScriptMethod -Name LogDebug -Value {
  Param([Parameter(Mandatory=$true)][string]$Message)
  $this.Log($Message, 'Debug')
}
$logger | Add-Member -Type ScriptMethod -Name LogInfo -Value {
  Param([Parameter(Mandatory=$true)][string]$Message)
  $this.Log($Message, 'Information')
}
...

Write-Log 'foo'                    # default log level: Information
$logger.Log('foo')                 # default log level: Information
$logger.Log('foo', 'Information')  # explicit log level: Information
$logger.LogInfo('foo')             # (convenience) wrapper method
$logger.LogDebug('bar')

De cualquier manera, puede externalizar el código de registro mediante

  • ponerlo en un archivo de secuencia de comandos separado y obtener ese archivo:

    . 'C:pathtologger.ps1'
    
  • ponerlo en un módulo e importar ese módulo:

    Import-Module Logger
    

Para complementar la útil y completa respuesta de Ansgar:

Write-Host se convirtió (en esencia) en un envoltorio para
Write-Information -InformationAction Continue
en PSv5, presumiblemente porque:

  • eso permite suprimir o redirigir Write-Host mensajes, que antes no era posible (en PowerShell 4 o versiones anteriores, Write-Host omitió las transmisiones de PowerShell y la salida directamente al host),

  • tiempo preservando la compatibilidad con versiones anteriores en que los mensajes se emiten por defecto – a diferencia de Write-Information, cuyo comportamiento predeterminado es silencio (porque respeta la variable de preferencia $InformationPreference, cuyo valor predeterminado es SilentlyContinue).

Tiempo Write-Host por lo tanto, ahora (PSv5 +) es un nombre poco apropiado; no necesariamente escribe en el anfitrión más – todavía tiene una clara ventaja sobre Write-Information (como dices): puede producir de colores producción con -ForegroundColor y -BackgroundColor.


La respuesta de Ansgar tiene la tala convencional perspectiva cubierta, pero PowerShell Start-Transcript cmdlet mayo servir como incorporado alternativa (ver más abajo).

En cuanto a tu deseo de enviar mensajes al host al mismo tiempo que los captura en un archivo de registro:

De PowerShell transcripciones de la sesión – vía Start-Transcript y Stop-Transcriptmayo darte lo que quieras.

Como el nombre sugiere, las transcripciones capturan cualquier impresión en la pantalla (sin colorear), que por lo tanto por defecto incluye salida de éxito, sin embargo.
Aplicado a tu ejemplo:

$null = Start-Transcript "D:foo.log"

$InformationPreference = "Continue"
Write-Information "Some Message"
Write-Information "Another Message"

$null = Stop-Transcript

Lo anterior imprimirá mensajes a ambos la pantalla y el archivo de transcripción; nota que, curiosamente, solo en el expediente estarán prefijados con INFO:.
(Por el contrario, Write-Warning, Write-Verbose y Write-Debug – si está configurado para producir salida – use prefijo WARNING:, VERBOSE:, DEBUG: tanto en pantalla como en el archivo; similar, Write-Error produce una entrada multilínea “ruidosa” tanto en la pantalla como en el archivo).

Nota uno insecto ese solo afecta Windows PowerShell (se ha solucionado en PowerShell [Core].Gracias, JohnLBevan.): salida de Write-Information aparece en el archivo de transcripción (pero no en la pantalla) incluso cuando $InformationPreference se establece en SilentlyContinue (el valor por defecto); la única forma de excluir Write-Information salida (a través de la variable de preferencia o -InformationAction parámetro) parece ser un valor de Ignore – que silencia categóricamente la salida – o, curiosamente, Continue, en el que solo se imprime en el consola, como señala PetSerAl.

En una palabra, puedes usar Start-Transcript como un conveniente, incorporado aproximación de una instalación de registro, cuya verbosidad puede controlar desde el exterior a través de las variables de preferencia ($InformationPreference, $VerbosePreference, …), con lo siguiente diferencias importantes de la tala convencional:

  • Generalmente, lo que entra en el archivo de transcripción es además salida a la consola (que en general podría considerarse una ventaja).

  • Sin embargo, éxito salida (salida de datos) es por defecto además enviado a la transcripción – a menos que usted capturar eso o reprimir por completo, y no puede excluirlo selectivamente de la transcripción:

    • Si lo captura o lo suprime, tampoco se mostrará en el host (la consola, por defecto)[1].

    • Lo contrario, sin embargo, es posible: puede enviar la salida a la transcripción solo (sin hacer eco en la consola), a través de Out-Default -Transcript Gracias, PetSerAl; p.ej,
      'to transcript only' | Out-Default -Transcript; sin embargo, a partir de PowerShell 7.0, esto parece registrar la salida dos veces en la transcripción; también tenga en cuenta que Out-Default generalmente no está destinado a ser llamado desde el código de usuario; consulte esta respuesta.

  • Generalmente, redirecciones externas (aplicando > a una llamada a un script que realiza la transcripción internamente) mantener las corrientes fuera de la transcripción, con dos excepciones, a partir de PowerShell 7.0:

    • Write-Host salida, incluso si 6> o *> se utilizan redirecciones.
    • Salida de error, incluso si 2> o *> se utilizan redirecciones.
      Sin embargo, usando $ErrorActionPreference="SilentlyContinue" / 'Ignore' lo hace guardar Sin terminar errores de la transcripción, pero no terminando unos.
  • Los archivos de transcripción no están orientados a líneas (hay un bloque de líneas de encabezado con información de invocación y no hay garantía de que la salida producida por el script se limite a una línea), por lo que no puede esperar analizarlos línea por línea conducta.


[1] PetSerAl menciona la siguiente solución alternativa limitada y algo engorrosa (PSv5 +) para enviar resultados exitosos solo a la consola, lo que excluye notablemente enviar el resultado a través de la canalización o capturarlo:
'to console only' | Out-String -Stream | ForEach-Object { $Host.UI.WriteLine($_) }

PowerShell se trata de automatización.

A veces, ejecuta un script varias veces al día y no desea ver el resultado todo el tiempo.

Write-Host no tiene posibilidad de ocultar la salida. Se escribe en la consola, pase lo que pase.

Con Write-Information, puede especificar el -InformationAction Parámetro en el Script. Con este parámetro, puede especificar si desea ver los mensajes (-InformationAction Continue) o no (-InformationAction SilentlyContinue)

Editar: Y por favor use "Some Message" | out-file D:foo.log para la tala, y tampoco Write-Host o Write-Information

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *