PowerShell 5 中的写入主机与写入信息

2024-04-20

众所周知,Write-Host是邪恶的。 在PowerShell 5, Write-Information被添加并被考虑替换Write-Host.

但是,说实话,哪个更好呢?
Write-Host是邪恶的,因为它不使用管道,因此输入消息无法被重用。
但是,什么Write-Hostdo 只是在控制台中显示一些内容,对吗?在什么情况下我们应该重用输入?
不管怎样,如果我们真的想重用输入,为什么不直接写这样的东西:

$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 and -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-InformationWrite-Host,请在这里留下您的好意答案。
谢谢。


The Write-*cmdlet 允许您以结构化方式引导 PowerShell 代码的输出,因此您可以轻松地区分不同严重性的消息。

  • Write-Host:在控制台上向交互式用户显示消息。与其他不同Write-*这个 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 登录方法。例如,您可以实现单个日志记录功能,例如@杰里米蒙哥马利 https://stackoverflow.com/a/38537613/1630171他在回答中建议:

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')

无论哪种方式,您都可以通过以下方式外部化日志记录代码

  • 将其放入单独的脚本文件中并点源 https://technet.microsoft.com/en-us/library/hh847841.aspx该文件:

    . 'C:\path\to\logger.ps1'
    
  • 把它放入一个module https://msdn.microsoft.com/en-us/library/dd878340%28v=vs.85%29.aspx并导入该模块:

    Import-Module Logger
    
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PowerShell 5 中的写入主机与写入信息 的相关文章

随机推荐