拆分PowerShell管道以分隔文件

时间:2015-04-19 17:40:28

标签: powershell pipeline

在测试期间,我正在创建的函数输出标准输出和详细输出。现在,这些都最终在同一个日志文件中。我想把它们分开。

举个例子:

Function Test-Output {
    [CmdletBinding()]
    Param ()
    Get-Process PowerShell, none
    Write-Warning "Test!"
    Write-Verbose "Test Verbose"
    Write-Debug "Test Debug"
}

如果我运行它:

Test-Output -Verbose -Debug

...我得到了none - 进程(管道2)的错误流:

Get-Process : Cannot find a process with the name "none". Verify the process name and call the cmdlet again.
At line:4 char:1
+ Get-Process PowerShell, none
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (none:String) [Get-Process], ProcessCommandException
    + FullyQualifiedErrorId : NoProcessFoundForGivenName,Microsoft.PowerShell.Commands.GetProcessCommand

...我的成功流(管道1):

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    360      33    98736     109172   673     5.44   6220 powershell 

...警告流(管道3):WARNING: Test!

...详细信息流(管道4):VERBOSE: Test Verbose

...和调试流(管道5):DEBUG: Test Debug

到目前为止,我发现将每个流都放入自己的文件中的唯一(粗略)解决方案就是这个(为了方便起见,我已将Out-File替换为Write-Output):

Test-Output -ErrorVariable ErrorVar -WarningVariable WarningVar -OutVariable OutVar -Debug -Verbose *> $Null
Write-Output "Error : $ErrorVar"
Write-Output "Warning : $WarningVar"
foreach ($Record in $Outvar) {
    If ($Record.GetType().Name -eq 'VerboseRecord') { Write-Output "Verbose : $($Record.Message)" }
    ElseIf ($Record.GetType().Name -eq 'DebugRecord') { Write-Output "Debug : $($Record.Message)" }
    Else { $Record }
}

当我尝试更简单的解决方案时,我最终错过了错误和警告流(我仍然需要使用上面的foreach拆分它们):

Test-Output -Verbose -Debug *> $OutVar
# $OutVar contains Pipeline(1), Verbose(4) and Debug (5)
# Error(2) and Warning (3) seem to be gone (not counting $error[0])

Test-Output -Verbose -Debug 2>&1 3>&1 *> $OutVar
# Error(2) and Warning (3) still gone

Test-Output -Verbose -Debug *>&1 > $OutVar
# Same Thing

到目前为止,Tee-Object似乎并没有完全符合我的要求。

所以我的问题是:我在这里想的太复杂了,有没有更简单的解决方案?如果是这样,是什么?

1 个答案:

答案 0 :(得分:1)

一种选择是使用运行空间。然后,您可以分别处理输出和每个流输出:

Function Test-Output {
[CmdletBinding()]
Param ()

$Code = {
$VerbosePreference,$WarningPreference,$DebugPreference = 'Continue'
Get-Process PowerShell, none
Write-Warning "Test!"
Write-Verbose "Test Verbose"
Write-Debug "Test Debug"
}

$newPowerShell = [PowerShell]::Create().AddScript($code)
$job = $newPowerShell.BeginInvoke()
While (-Not $job.IsCompleted) {}

[PSCustomObject]@{
  OutPut  = $newPowerShell.EndInvoke($job)
  Verbose = $newPowerShell.Streams.Verbose.ReadAll()
  Warning = $newPowerShell.Streams.Warning.ReadAll()
  Error   = $newPowerShell.Streams.Error.ReadAll()
 }

 $newPowerShell.Dispose()
}

$Result = Test-Output 

这会将自定义对象返回给$ Result,并为调用中的每个流提供单独的属性。