我试图基于从我的cmdlet发出的流,将事件日志输出到正确的条目类型(信息,警告,错误),如下所示:
function myfunction {
Param(
[switch]$stream1,
[switch]$stream2
)
if ($stream1) {write-output 'stream 1 msg'}
if ($stream2) {write-error 'stream 2 msg'}
}
$eventlogparams = @{'logname'='application';'source'='myapp';'eventid'='1'}
myfunction -stream1 -stream2 `
1> write-eventlog @eventlogparams -entrytype information -message $_ `
2> write-eventlog @eventlogparams -entrytype error -message $_
有人知道如何做到这一点吗?
答案 0 :(得分:3)
您可以 合并错误流和其他错误流到成功流,并通过在源流之间进行区分。每个管道对象的数据类型 :
myfunction -channel1 -channel2 *>&1 | ForEach-Object {
$entryType = switch ($_.GetType().FullName) {
'System.Management.Automation.ErrorRecord' { 'error'; break }
'System.Management.Automation.WarningRecord' { 'warning'; break }
default { 'information'}
}
write-eventlog @eventlogparams -entrytype $entryType -message $_
}
重定向*>&1
将所有所有(*
)流的输出发送到(&
)成功流(1
),以便所有输出,无论它来自什么流,都通过管道发送。
以上内容仅专门处理错误和警告,并将其他信息(包括成功输出)报告为信息,但扩展方法很容易-请参见底部。
请参见about_Redirections,以了解PowerShell(自v6起)中可用的全部6个输出流。
以一个更简单的示例来说明该技术:
& { Write-Output good; Write-Error bad; Write-Warning problematic } *>&1 | ForEach-Object {
$entryType = switch ($_.GetType().FullName) {
'System.Management.Automation.ErrorRecord' { 'error'; break }
'System.Management.Automation.WarningRecord' { 'warning'; break }
default { 'information'}
}
'[{0}] {1}' -f $entryType, $_
}
以上结果:
[information] good
[error] bad
[warning] problematic
各种流输出的数据类型的列表:
Stream Type
------ ----
#1 (Success) (whatever input type is provided).
#2 (Error) [System.Management.Automation.ErrorRecord]
#3 (Warning) [System.Management.Automation.WarningRecord]
#4 (Verbose) [System.Management.Automation.VerboseRecord]
#5 (Debug) [System.Management.Automation.DebugRecord]
#6 (Information) [System.Management.Automation.InformationRecord]
以下代码用于生成以上列表(第一个数据行除外):
& {
$VerbosePreference = $DebugPreference = $InformationPreference = 'Continue'
$ndx = 2
"Write-Error", "Write-Warning", "Write-Verbose", "Write-Debug", "Write-Information" | % {
& $_ ($_ -split '-')[-1] *>&1
++$ndx
} | Select-Object @{n='Stream'; e={"#$ndx ($_)"} }, @{n='Type'; e={"[$($_.GetType().FullName)]"} }
}
答案 1 :(得分:1)
正如@Lee_Dailey正确指出的那样,您需要事件源存在。即使在那之后,您的代码片段也可能会抛出错误(如PS v5中已选中)
该进程无法访问文件 'C:\ Users \ username \ Desktop \ write-eventlog',因为它正在被使用 另一个过程。
因为重定向操作符期望文件不重定向cmdlet或函数,所以这是导致上述错误的原因。
您可以尝试修改代码,以便重定向操作员将数据存储在文件中,然后将其推送到事件日志中:
myfunction -channel1 -channel2 > output.txt 2> error.txt
write-eventlog @eventlogparams -entrytype error -message ((get-content error.txt) -join "")
write-eventlog @eventlogparams -entrytype information -message ((get-content output.txt) -join "")
另一种方法是使用outvariable和errorvariable,为此,该功能必须是高级功能(为此我添加了cmdletbinding):
function myfunction {
[CmdletBinding()]
Param(
[switch]$channel1,
[switch]$channel2
)
if ($channel1) {write-output 'channel 1 msg'}
if ($channel2) {write-error 'channel 2 msg'}
}
$eventlogparams = @{'logname'='application';'source'='myapp';'eventid'='1'}
myfunction -channel1 -channel2 -OutVariable output -ErrorVariable errordata
write-eventlog @eventlogparams -entrytype error -message ($errordata -join "")
write-eventlog @eventlogparams -entrytype information -message ($output -join "")