【问题标题】:powershell cmdlet how to pipe information or error to write-eventlogpowershell cmdlet 如何将信息或错误通过管道传输到 write-eventlog
【发布时间】:2018-11-10 17:54:47
【问题描述】:

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

有没有人知道如何做到这一点?

【问题讨论】:

  • 您需要在目标系统上命名为myappsource。使用New-Eventlog cmdlet 及其-Source 参数创建。看看这篇文章... 如何使用 PowerShell 写入事件日志 – 嘿,脚本专家!博客 — blogs.technet.microsoft.com/heyscriptingguy/2013/06/20/…
  • @Lee_Dailey:我认为Write-EventLog 参数只是示例。如果我理解正确,OP 的愿望是处理来自 all 流(或至少来自成功和错误流)的输出,并能够区分输入来自哪个流,以便行为可以相应地调整(在这种情况下选择适当的事件类别)。
  • @mklement0 - 这是有道理的。 [grin] 我仍然不确定 OP 是否知道 Source 必须首先存在。这是我第一次尝试写入自定义事件日志时看到人们提到的最常见的错误。
  • 我已经知道需要事先创建源
  • @ErikW - 感谢您澄清这一点! [咧嘴]

标签: powershell event-log io-redirection


【解决方案1】:

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

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

【讨论】:

  • 在您的第一个示例中,我必须在 Write-Error 调用中使用-ErrorAction Continue,否则脚本将因错误而停止。同样,对于第二个示例,我必须使用 & $_ ($_ -split '-')[-1] -Erroraction Continue *>&1 才能使其工作。
  • @bielawski:仅当您将首选项变量 $ErrorActionPreference 从默认的 'Continue' 更改为 'Stop' 时才需要这样做。将-Erroraction Continue 传递给& { ... } 不作为-ErrorAction 常用参数;只有 cmdlet 和高级脚本/函数可以识别它。
【解决方案2】:

正如@Lee_Dailey 正确指出的那样,您需要存在事件源。即使在那之后,您的 sn-p 也可能会抛出类似错误(在 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 "")

【讨论】:

  • Quib​​ble:错误原因是同一文件被两次定位; PowerShell 非常乐意写入名为write-eventlog 的文件,但不是通过竞争相同输出文件的重定向。另外,我不确定其意图是将收集的流输出写为 single 事件日志记录。
  • 这个问题是它收集所有到一个变量,你可以做一个 foreach 语句稍后拆分到事件日志,但我试图在事情完成后实时写入事件日志在我的函数里面
  • @mklement0 是的。我从错误消息中了解到,我应该在答案中更好地阐明这一点
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-08
  • 1970-01-01
  • 1970-01-01
  • 2019-01-24
  • 2019-12-05
  • 2020-10-08
  • 1970-01-01
相关资源
最近更新 更多