简体   繁体   English

powershell cmdlet如何通过管道将信息或错误写入事件日志

[英]powershell cmdlet how to pipe information or error to write-eventlog

i'm trying to output to eventlog to the correct Entry Type (Information,Warning,Error) based on the stream that is coming out of my cmdlet, something like this: 我试图基于从我的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 $_

does anyone have an idea of how to accomplish this? 有谁知道如何做到这一点?

You can merge the error stream and others into the success stream and distinguish between the origin streams by the data type of each pipeline object: 您可以错误流和其他错误流合并成功流中,通过每个管道对象数据类型区分原始流

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 $_
}

Redirection *>&1 sends the output from all ( * ) streams to ( & ) the success stream ( 1 ), so that all output, irrespective of what stream it came from, is sent through the pipeline . 重定向*>&1所有* )流的输出发送到( & )成功流( 1 ),以便所有输出,无论它来自什么流,都通过管道发送。

The above only deals with errors and warnings specifically, and reports everything else, including the success output, as information, but it's easy to extend the approach - see bottom. 上面仅专门处理错误和警告,并将其他所有信息(包括成功输出)报告为信息,但扩展方法很容易-请参见底部。

See about_Redirections for an overview of all 6 output streams available in PowerShell (as of v6). 请参阅about_Redirections以了解PowerShell(自v6起)中可用的所有6个输出流的概述。


To illustrate the technique with a simpler example: 用一个简单的例子来说明这种技术:

& { 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, $_
}

The above yields: 以上收益:

[information] good
[error] bad
[warning] problematic

The list of data types output by the various streams : 各种流输出的数据类型列表

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]

The following code was used to produce the above list (except for the first data row): 以下代码用于生成以上列表(第一个数据行除外):

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

As @Lee_Dailey rightly pointed , you need the event source to exist.Even after that,Your snippet might throw error like (checked in PS v5) 正如@Lee_Dailey正确指出的那样,您需要事件源存在。即使在那之后,您的代码段也可能会抛出错误,例如(在PS v5中选中)

The process cannot access the file 'C:\\Users\\username\\Desktop\\write-eventlog' because it is being used by another process. 该进程无法访问文件'C:\\ Users \\ username \\ Desktop \\ write-eventlog',因为它正在被另一个进程使用。

because redirection operator expects a file to redirect not a cmdlet or function that's the reason for the above error. 因为重定向操作员希望文件重定向的不是cmdlet或函数,所以这是导致上述错误的原因。

you can try modifying the code so that redirection operator stores the data in files and then push that into event log: 您可以尝试修改代码,以便重定向运算符将数据存储在文件中,然后将其推送到事件日志中:

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

Another method is using outvariable and errorvariable , for this to work the function must be advanced function (I have added cmdletbinding for that): 另一种方法是使用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 "")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM