powershell cmdlet 如何将信息或错误通过管道传输到 write-eventlog

powershell cmdlet how to pipe information or error to write-eventlog

我正在尝试根据从我的 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 $_

有人知道如何实现吗?

正如@Lee_Dailey 所指出的那样,您之后需要将事件源指向 exist.Even,您的代码片段可能会抛出错误(已在 PS v5 中检查)

The process cannot access the file 'C:\Users\username\Desktop\write-eventlog' because it is being used by another process.

因为重定向运算符期望重定向的文件不是 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 "")

您可以合并错误流和其他流到成功通过每个管道对象的数据类型区分源流:

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 将来自 all (*) 流的输出发送到 (&) 成功流 (1), 这样所有的输出,不管它来自什么流,都通过 pipeline.

发送

以上仅专门处理错误和警告,并将其他所有内容(包括成功输出)报告为信息,但很容易扩展该方法 - 请参阅底部。

有关 PowerShell 中可用的所有 6 个输出流的概述(从 v6 开始),请参阅 about_Redirections


用一个更简单的例子来说明该技术:

& { 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)]"} }
}