众所周知Write-Host
是邪恶的。
在PowerShell 5
中,添加了Write-Information
并被认为可以替换Write-Host
。
但是,真的,哪个更好?Write-Host
邪恶,因为它不使用管道,因此输入消息无法重用。
但是,Write-Host
要做的只是在控制台中显示某些内容呢?在什么情况下我们应该重用输入?
无论如何,如果我们真的想重用输入,为什么不写这样的东西:
$foo = "Some message to be reused like saving to a file"
Write-Host $foo
$foo | Out-File -Path "D:\foo.log"
Write-Host
的另一个缺点是,可以使用
Write-Host
和
-ForegroundColor
来指定
-BackgroundColor
以哪种颜色在控制台中显示消息。
另一方面,通过使用
Write-Information
,输入消息可以通过6号管道在任何需要的地方使用。并且不需要像我上面写的那样编写额外的代码。但这是不利的一面,如果我们想将消息写入控制台并保存到文件中,则必须这样做:
# Always set the $InformationPreference variable to "Continue"
$InformationPreference = "Continue";
# if we don't want something like this:
# ======= Example 1 =======
# File Foo.ps1
$InformationPreference = "Continue";
Write-Information "Some Message"
Write-Information "Another Message"
# File AlwaysRunThisBeforeEverything.ps1
.\Foo.ps1 6>"D:\foo.log"
# ======= End of Example 1 =======
# then we have to add '6>"D:\foo.log"' to every lines of Write-Information like this:
# ======= Example 2 =======
$InformationPreference = "Continue";
Write-Information "Some Message" 6>"D:\foo.log"
Write-Information "Another Message" 6>"D:\foo.log"
# ======= End of Example 2 =======
我认为有点多余。
我只了解“与”这件事的一小部分,并且在我脑海中一定有一些东西。还有什么让我相信
Write-Information
比
Write-Host
更好的东西了,请在这里留下您的好答案。
谢谢。
请您参考如下方法:
Write-*
cmdlet允许您以结构化的方式引导PowerShell代码的输出,因此您可以轻松地区分不同严重性的消息。
Write-Host
:在控制台上向交互用户显示消息。与其他Write-*
cmdlet不同,此cmdlet不适合也不旨在用于自动化/重定向目的。不邪恶,只是不同。 Write-Output
:将代码的“正常”输出写入默认(成功)输出流(“STDOUT”)。 Write-Error
:将错误信息写入单独的流(“STDERR”)。 Write-Warning
:将您认为是警告的消息(即不是故障,而是用户应注意的事情)写到单独的流中。 Write-Verbose
:将您认为比“普通”输出更为冗长的信息写入单独的流。 Write-Debug
:将您认为与调试代码有关的信息写到单独的流中。 Write-Information
只是这种方法的延续。它允许您在输出中实现日志级别(
Debug
,
Verbose
,
Information
,
Warning
,
Error
),并且仍然具有可用于常规输出的成功输出流。
至于为什么
Write-Host
变成
Write-Information
的包装器:我不知道此决定的实际原因,但我怀疑这是因为大多数人不了解
Write-Host
的实际工作原理,即它可以用于什么以及它的用途。不应该用于。
据我所知,没有一种普遍接受或推荐的登录PowerShell的方法。例如,您可以实现单个日志记录功能,例如 @JeremyMontgomery在他的答案中建议的功能:
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'
或一组日志记录功能(每个日志级别一个):
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'
另一种选择是创建自定义记录器对象:
$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')
无论哪种方式,您都可以通过以下方式外部化日志记录代码
. 'C:\path\to\logger.ps1'
Import-Module Logger