PowerShell 技能连载 - Working with Get-WinEvent

如果您想从 Windows 事件日志中读取系统事件,Get-Eventlog 是个易于使用且简单的选择。这段代码能够获取最新的 10 个错误和警告事件:

1
PS> Get-EventLog -LogName System -EntryType Error,Warning -Newest 10

不幸的是,Get-Eventlog 已被弃用,并且它不再可用于 PowerShell 7。弃用有很明显的原因:该 cmdlet 只能从“经典”日志文件中读取,它很缓慢并且具有其他限制。

这就是为什么 PowerShell 在3.0版中推出更好的替代命令:Get-WinEvent。PowerShell 7 也有此 cmdlet。

Unfortunately, Get-WinEvent is much harder to use because there are no intuitive parameters, and instead your filter criteria needs to be specified as a hash table.
不幸的是,Get-Winevent 更难使用,因为没有直观的参数,而是需要通过哈希表指定过滤条件。

但是,通过“代理函数”,您可以指导 Get-WinEvent 使用您所熟悉的旧式参数。以下是代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
<#Suggestion to improve Get-WinEvent in order to make it compatible to the commonly used Get-EventLog callsBelow is a prototype using a proxy function. Run it to enhance Get-WinEvent.To get rid of the enhancement, either restart PowerShell or run:Remove-Item -Path function:Get-WinEventNote that the prototype emits the composed hash table to the console (green)
\#>function Get-WinEvent
{ [CmdletBinding(DefaultParameterSetName='GetLogSet', HelpUri='https://go.microsoft.com/fwlink/?LinkID=138336')]
param(

[Parameter(ParameterSetName='ListLogSet', Mandatory=$true, Position=0)]
[AllowEmptyCollection()]
[string[]]
${ListLog}, [Parameter(ParameterSetName='LogNameGetEventlog', Mandatory=$true, Position=0)] <#NEW\#>
[Parameter(ParameterSetName='GetLogSet', Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
[string[]]
${LogName}, [Parameter(ParameterSetName='ListProviderSet', Mandatory=$true, Position=0)]
[AllowEmptyCollection()]
[string[]]
${ListProvider}, <# Get-EventLog supports wildcards, Get-WinEvent does not. Needs to be corrected. #> [Parameter(ParameterSetName='GetProviderSet', Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]
[string[]]
${ProviderName}, [Parameter(ParameterSetName='FileSet', Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]
[Alias('PSPath')]
[string[]]
${Path}, [Parameter(ParameterSetName='FileSet')]
[Parameter(ParameterSetName='GetProviderSet')]
[Parameter(ParameterSetName='GetLogSet')]
[Parameter(ParameterSetName='HashQuerySet')]
[Parameter(ParameterSetName='XmlQuerySet')]
[ValidateRange(1, 9223372036854775807)]
[long]
${MaxEvents},
<# NEW \#> [Parameter(ParameterSetName='LogNameGetEventlog')]
[ValidateRange(0, 2147483647)]
[int]
${Newest},
[Parameter(ParameterSetName='GetProviderSet')]
[Parameter(ParameterSetName='ListProviderSet')]
[Parameter(ParameterSetName='ListLogSet')]
[Parameter(ParameterSetName='GetLogSet')]
[Parameter(ParameterSetName='HashQuerySet')]
[Parameter(ParameterSetName='XmlQuerySet')]
[Parameter(ParameterSetName='LogNameGetEventlog')] <#NEW\#>
[Alias('Cn')]
[ValidateNotNullOrEmpty()] <#CORRECTED\#> [string] <# used to be [String[]], Get-WinEvent accepts [string] only, should be changed to accept string arrays \#> ${ComputerName}, [Parameter(ParameterSetName='GetProviderSet')]
[Parameter(ParameterSetName='ListProviderSet')]
[Parameter(ParameterSetName='ListLogSet')]
[Parameter(ParameterSetName='GetLogSet')]
[Parameter(ParameterSetName='HashQuerySet')]
[Parameter(ParameterSetName='XmlQuerySet')]
[Parameter(ParameterSetName='FileSet')]
[pscredential]
[System.Management.Automation.CredentialAttribute()]
${Credential}, [Parameter(ParameterSetName='FileSet')]
[Parameter(ParameterSetName='GetProviderSet')]
[Parameter(ParameterSetName='GetLogSet')]
[ValidateNotNull()]
[string]
${FilterXPath}, [Parameter(ParameterSetName='XmlQuerySet', Mandatory=$true, Position=0)]
[xml]
${FilterXml}, [Parameter(ParameterSetName='HashQuerySet', Mandatory=$true, Position=0)]
[hashtable[]]
${FilterHashtable}, [Parameter(ParameterSetName='GetProviderSet')]
[Parameter(ParameterSetName='ListLogSet')]
[Parameter(ParameterSetName='GetLogSet')]
[Parameter(ParameterSetName='HashQuerySet')]
[switch]
${Force}, [Parameter(ParameterSetName='GetLogSet')]
[Parameter(ParameterSetName='GetProviderSet')]
[Parameter(ParameterSetName='FileSet')]
[Parameter(ParameterSetName='HashQuerySet')]
[Parameter(ParameterSetName='XmlQuerySet')]
[switch]
${Oldest},
<# NEW \#> [Parameter(ParameterSetName='LogNameGetEventlog')]
[ValidateNotNullOrEmpty()]
[datetime]
${After}, <# NEW \#> [Parameter(ParameterSetName='LogNameGetEventlog')]
[ValidateNotNullOrEmpty()]
[datetime]
${Before},
<# NEW \#> [Parameter(ParameterSetName='LogNameGetEventlog')]
[ValidateNotNullOrEmpty()]
[string[]]
${UserName}, <# NEW \#> [Parameter(ParameterSetName='LogNameGetEventlog', Position=1)]
[ValidateRange(0, 9223372036854775807)]
[ValidateNotNullOrEmpty()]
[long[]]
${InstanceId}, <# NEW \#> [Parameter(ParameterSetName='LogNameGetEventlog')]
[ValidateNotNullOrEmpty()]
[ValidateRange(1, 2147483647)]
[int[]]
${Index}, <# NEW \#> [Parameter(ParameterSetName='LogNameGetEventlog')]
[Alias('ET')]
[ValidateNotNullOrEmpty()]
[ValidateSet('Error','Information','FailureAudit','SuccessAudit','Warning')]
[string[]]
${EntryType}, <# NEW \#> [Parameter(ParameterSetName='LogNameGetEventlog')]
[Alias('ABO')]
[ValidateNotNullOrEmpty()]
[string[]]
${Source}, <# NEW \#> [Parameter(ParameterSetName='LogNameGetEventlog')]
[Alias('MSG')]
[ValidateNotNullOrEmpty()]
[string]
${Message}, <# NEW \#> [Parameter(ParameterSetName='LogNameGetEventlog')]
[switch]
${AsBaseObject},
[Parameter(ParameterSetName='ListGetEventlog')]
[switch]
${List}, [Parameter(ParameterSetName='ListGetEventlog')]
[switch]
${AsString}



)

begin {
try {
$outBuffer = $null if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
{
$PSBoundParameters['OutBuffer'] = 1 }
$wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Diagnostics\Get-WinEvent', [System.Management.Automation.CommandTypes]::Cmdlet)

\# if the user chose the Get-EventLog compatible parameters, \# compose the appropriate filter hash table $scriptCmd = if ($PSCmdlet.ParameterSetName -eq 'LogNameGetEventlog')
{
\# mandatory parameter $filter = @{
LogName = $PSBoundParameters['Logname']
}
$null = $PSBoundParameters.Remove('LogName')

if ($PSBoundParameters.ContainsKey('Before'))
{
$filter['EndTime'] = $PSBoundParameters['Before']
$null = $PSBoundParameters.Remove('Before')
}
if ($PSBoundParameters.ContainsKey('After'))
{
$filter['StartTime'] = $PSBoundParameters['After']
$null = $PSBoundParameters.Remove('After')
}
if ($PSBoundParameters.ContainsKey('EntryType'))
{
\# severity is translated to an integer array
$levelFlags = [System.Collections.Generic.List[int]]@()

\# string input converted to integer array if ($PSBoundParameters['EntryType'] -contains 'Error')
{
$levelFlags.Add(1) \# critical $levelFlags.Add(2) \# error }
if ($PSBoundParameters['EntryType'] -contains 'Warning')
{
$levelFlags.Add(3) \# warning }
if ($PSBoundParameters['EntryType'] -contains 'Information')
{
$levelFlags.Add(4) \# informational $levelFlags.Add(5) \# verbose }


\# default to 0 if ($levelFlags.Count -gt 0)
{
$filter['Level'] = [int[]]$levelFlags }

\# audit settings stored in Keywords key if ($PSBoundParameters['EntryType'] -contains 'FailureAudit')
{
$filter['Keywords'] += 0x10000000000000 }
if ($PSBoundParameters['EntryType'] -contains 'SuccessAudit')
{
$filter['Keywords'] += 0x20000000000000 }
$null = $PSBoundParameters.Remove('EntryType')
}
if ($PSBoundParameters.ContainsKey('InstanceId'))
{
$filter['ID'] = $PSBoundParameters['InstanceId']
$null = $PSBoundParameters.Remove('InstanceId')
}
if ($PSBoundParameters.ContainsKey('Source'))
{
$filter['ProviderName'] = $PSBoundParameters['Source']
$null = $PSBoundParameters.Remove('Source')
}

$PSBoundParameters['FilterHashtable'] = $filter Write-Host ($filter | Out-String) -ForegroundColor Green
if ($PSBoundParameters.ContainsKey('Newest'))
{
$PSBoundParameters['MaxEvents'] = $PSBoundParameters['Newest']
$null = $PSBoundParameters.Remove('Newest')
}
}


$scriptCmd =
{
& $wrappedCmd @PSBoundParameters }
$steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
$steppablePipeline.Begin($PSCmdlet)
} catch {
throw }
}

process {
try {
$steppablePipeline.Process($_)
} catch {
throw }
}

end {
try {
$steppablePipeline.End()
} catch {
throw }
}
<#

.ForwardHelpTargetName Microsoft.PowerShell.Diagnostics\Get-WinEvent .ForwardHelpCategory Cmdlet \#>}

当您执行完这个函数,就可以通过您在 Get-EventLog 中熟悉的相同参数使用 Get-WinEvent

1
2
3
4
5
6
PS> Get-WinEvent -LogName System -EntryType Error,Warning -Newest 10

Name Value
---- -----
LogName {System}
Level {1, 2, 3}

您还可以获得基于参数使用的哈希表过滤器的键和值。

PowerShell 技能连载 - Working with Get-WinEvent

http://blog.vichamp.com/2021/10/22/working-with-get-winevent/

作者

吴波

发布于

2021-10-22

更新于

2022-07-06

许可协议

评论