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

给你一囗甜甜゛ 提交于 2020-08-25 09:01:42

问题


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:

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?


回答1:


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.

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


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



回答2:


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)

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

because redirection operator expects a file to redirect not a cmdlet or function that's the reason for the above error.

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

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


来源:https://stackoverflow.com/questions/53241825/powershell-cmdlet-how-to-pipe-information-or-error-to-write-eventlog

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!