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 otroWrite-*
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 esSilentlyContinue
).
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-Transcript
– mayo 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 queOut-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 si6>
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