Skip to main content
 首页 » 编程设计

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

2024年11月24日27haluo1

众所周知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-InformationWrite-Host更好的东西了,请在这里留下您的好答案。
谢谢。

请您参考如下方法:

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

  • Write-Host:在控制台上向交互用户显示消息。与其他Write-* cmdlet不同,此cmdlet不适合也不旨在用于自动化/重定向目的。不邪恶,只是不同。
  • Write-Output:将代码的“正常”输出写入默认(成功)输出流(“STDOUT”)。
  • Write-Error:将错误信息写入单独的流(“STDERR”)。
  • Write-Warning:将您认为是警告的消息(即不是故障,而是用户应注意的事情)写到单独的流中。
  • Write-Verbose:将您认为比“普通”输出更为冗长的信息写入单独的流。
  • Write-Debug:将您认为与调试代码有关的信息写到单独的流中。
  • Write-Information只是这种方法的延续。它允许您在输出中实现日志级别( DebugVerboseInformationWarningError),并且仍然具有可用于常规输出的成功输出流。

    至于为什么 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') 
    

    无论哪种方式,您都可以通过以下方式外部化日志记录代码
  • 将其放入单独的脚本文件中,然后dot-sourcing该文件:
    . 'C:\path\to\logger.ps1' 
    
  • 将其放入module并导入该模块:
    Import-Module Logger