将Write-Host语句重定向到文件

时间:2011-04-07 23:10:35

标签: powershell

我有一个我正在调试的powershell脚本,并希望将所有写主机语句重定向到一个文件。有没有一种简单的方法可以做到这一点?

12 个答案:

答案 0 :(得分:16)

  

在PowerShell 4.0之前,Write-Host将对象发送给主机。它不会返回任何对象。

     

从PowerShell 5.0及更新版本开始,Write-HostWrite-Information的包装器,允许输出到信息流并使用6>> file_name重定向。

http://technet.microsoft.com/en-us/library/hh849877.aspx

但是,如果你有很多Write-Host语句,请用Write-Log替换它们,这可以让你决定输出到控制台,文件或事件日志,还是全部三个。

检查:

答案 1 :(得分:14)

您可以为Write-Host创建一个代理函数,它将对象发送到标准输出流,而不是仅仅打印它们。我为此目的编写了下面的cmdlet。它将动态创建代理,仅在当前管道的持续时间内持续。

我的博客here上有完整的文章,但我已经在下面提供了代码。使用-Quiet开关禁止控制台写入。

用法:

PS> .\SomeScriptWithWriteHost.ps1 | Select-WriteHost | out-file .\data.log  # pipeline usage
PS> Select-WriteHost { .\SomeScriptWithWriteHost.ps1 } | out-file .\data.log  # scriptblock usage (safer)

function Select-WriteHost
{
   [CmdletBinding(DefaultParameterSetName = 'FromPipeline')]
   param(
     [Parameter(ValueFromPipeline = $true, ParameterSetName = 'FromPipeline')]
     [object] $InputObject,

     [Parameter(Mandatory = $true, ParameterSetName = 'FromScriptblock', Position = 0)]
     [ScriptBlock] $ScriptBlock,

     [switch] $Quiet
   )

   begin
   {
     function Cleanup
     {
       # clear out our proxy version of write-host
       remove-item function:\write-host -ea 0
     }

     function ReplaceWriteHost([switch] $Quiet, [string] $Scope)
     {
         # create a proxy for write-host
         $metaData = New-Object System.Management.Automation.CommandMetaData (Get-Command 'Microsoft.PowerShell.Utility\Write-Host')
         $proxy = [System.Management.Automation.ProxyCommand]::create($metaData)

         # change its behavior
         $content = if($quiet)
                    {
                       # in quiet mode, whack the entire function body, simply pass input directly to the pipeline
                       $proxy -replace '(?s)\bbegin\b.+', '$Object' 
                    }
                    else
                    {
                       # in noisy mode, pass input to the pipeline, but allow real write-host to process as well
                       $proxy -replace '(\$steppablePipeline\.Process)', '$Object; $1'
                    }  

         # load our version into the specified scope
         Invoke-Expression "function ${scope}:Write-Host { $content }"
     }

     Cleanup

     # if we are running at the end of a pipeline, need to immediately inject our version
     #    into global scope, so that everybody else in the pipeline uses it.
     #    This works great, but dangerous if we don't clean up properly.
     if($pscmdlet.ParameterSetName -eq 'FromPipeline')
     {
        ReplaceWriteHost -Quiet:$quiet -Scope 'global'
     }
   }

   process
   {
      # if a scriptblock was passed to us, then we can declare
      #   our version as local scope and let the runtime take it out
      #   of scope for us.  Much safer, but it won't work in the pipeline scenario.
      #   The scriptblock will inherit our version automatically as it's in a child scope.
      if($pscmdlet.ParameterSetName -eq 'FromScriptBlock')
      {
        . ReplaceWriteHost -Quiet:$quiet -Scope 'local'
        & $scriptblock
      }
      else
      {
         # in pipeline scenario, just pass input along
         $InputObject
      }
   }

   end
   {
      Cleanup
   }  
}

答案 2 :(得分:7)

使用重定向将导致Write-Host挂起。这是因为Write-Host处理特定于当前使用的终端的各种格式问题。如果您只是希望脚本具有正常输出的灵活性(默认为shell,具有>,2>等功能),请使用Write-Output。

否则,如果您真的想要捕捉当前终端的特性,Start-Transcript是一个很好的起点。否则你将不得不手工测试或编写一些复杂的测试套件。

答案 3 :(得分:5)

您可以在辅助PowerShell shell中运行脚本并捕获输出,如下所示:

powershell -File 'Your-Script.ps1' > output.log

这对我有用。

答案 4 :(得分:3)

这是我在我的第一篇PowerShell脚本中为我工作的,这是我几天前写的

function logMsg($msg)
{
    write-output $msg
    write-host $msg 
}

脚本中的用法:

logMsg("My Error Msg")
logMsg("My Info Msg")

powershell脚本执行调用:

ps> .\myFirstScript.ps1 >> testOutputFile.txt

这不是这个问题的答案,但可能会帮助某人尝试将日志记录到控制台并输出到某个日志文件,做到我在这里所做的事情:)

答案 5 :(得分:2)

定义一个名为Write-Host的函数。让它写入文件。如果某些调用使用一组奇怪的参数,您可能会遇到一些麻烦。此外,这仅适用于非Snapin限定的调用。

答案 6 :(得分:1)

刚刚在脚本顶部添加了Start-Transcript,在底部添加了Stop-Transcript。输出文件的目的是命名为<folder where script resides>-<datestamp>.rtf,但由于某种原因,跟踪文件被放在我没想到的地方 - 桌面!。

答案 7 :(得分:0)

如果您希望将消息包含在文件中,则不应使用Write-Host。它仅用于写入主机。

相反,您应该使用日志记录模块或Set / Add-Content。

答案 8 :(得分:0)

我发现处理此问题的最佳方法是使用日志记录功能来检测是否存在主机UI并采取相应措施。当脚本以交互模式执行时,它将在主机UI中显示详细信息,但是当它通过WinRM或非交互模式运行时,它将回退到写入输出,以便您可以使用{ {1}}或> redirection operators

*>

如果要使用写主机着色捕获完整输出,可以使用Get-ConsoleAsHtml.ps1脚本将主机的滚动缓冲区导出为html或RTF文件。

答案 9 :(得分:0)

使用Write-Output代替Write-Host并将其重定向到如下文件:

Deploy.ps1&gt; mylog.log或写输出“Hello World!” &GT; mylog.log

答案 10 :(得分:0)

尝试使用write-output而不是write-host。

输出沿着管道向下,但如果这是管道的末尾,它将进入控制台。

>write-output "test"
test
>write-output "test" > foo.txt
>get-content foo.txt
test

答案 11 :(得分:0)

尝试在尖括号 * 前添加星号 > 以重定向所有流:

<块引用>

powershell -File Your-Script.ps1 *> output.log

当请求流重定向时,如果没有指定特定的流,则默认情况下仅重定向 Success Stream(1>)。 Write-HostWrite-Information 的别名,它写入 Information Stream (6>)。要重定向所有流,请使用 *>

Powershell-7.1 支持多个输出流的重定向:

  • 成功流 (#1):PowerShell 2.0 Write-Output
  • 错误流 (#2):PowerShell 2.0 Write-Error
  • 警告流 (#3):PowerShell 3.0 Write-Warning
  • 详细流 (#4):PowerShell 3.0 Write-Verbose
  • 调试流 (#5):PowerShell 3.0 Write-Debug
  • 信息流 (#6):PowerShell 5.0 Write-Information
  • 所有流 (*):PowerShell 3.0