如何使用 PowerShell 由现有提供程序编写自定义事件日志?

How to write a custom event log by an already existing provider with PowerShell?

我正在尝试找出 'Network Connected' 事件日志消息中 "State" 数据的 Name/Value 映射:

Path = Microsoft-Windows-NetworkProfile/Operational
Source = NetworkProfile
Event ID = 10000

所以我想我会在更改消息的 "State" 值的同时由同一个提供者将自定义事件日志写入同一个日志(路径),然后我可以看到那个的名称映射事件查看器中的值。
例如,到目前为止,我有这些 Value/Name 映射:

1 --> 'Connected'
5 --> 'Connected, IPV4 (Local)'
9 --> 'Connected, IPV4 (Internet)'

我想知道其余的。

所以我尝试了 PowerShell 中的 New-WinEvent CmdLet 来写入日志:

New-WinEvent -ProviderName Microsoft-Windows-NetworkProfile -Id 10000 -Payload @("SSID","Description","{B58F86AB-F35D-4F73-A41E-98EA359E1D08}",0,1,0)

并且它被创建了,但是我传递给-Payload参数的最后4个参数没有生效。只有 {"name" = "SSID""Description" = "Description"} 出现在那个事件中。无论我如何更改最后 4 个参数都保持固定值,而执行此行时没有错误或警告,-Verbose 也没有显示任何内容。

我以所有可用的类型和值传递了这些参数(尤其是最后 3 个)。我什至将早期事件日志的参数(不是我记录的)传递给这个参数,怀疑我弄错了数据类型,但没有任何改变。

$a = ((Get-WinEvent -ProviderName Microsoft-Windows-NetworkProfile -MaxEvents 50  | Where-Object {$_.Id -eq 10000})[-1]).properties[3].value
$b = ((Get-WinEvent -ProviderName Microsoft-Windows-NetworkProfile -MaxEvents 50  | Where-Object {$_.Id -eq 10000})[-1]).properties[4].value
$c = ((Get-WinEvent -ProviderName Microsoft-Windows-NetworkProfile -MaxEvents 50  | Where-Object {$_.Id -eq 10000})[-1]).properties[5].value
New-WinEvent -ProviderName Microsoft-Windows-NetworkProfile -Id 10000 -Payload @("SSID","Description","{B58F86AB-F35D-4F73-A41E-98EA359E1D08}",$a,$b,$c)

然后我尝试了 Write-EventLog CmdLet:

Write-EventLog -LogName "Microsoft-Windows-NetworkProfile/Operational" -Source "NetworkProfile" -EventID 10000 -EntryType Information -Message $msg -Category 0

但我一直收到错误消息:Write-EventLog : The source name "NetworkProfile" does not exist on computer "localhost". 尽管来源确实存在并且它是 'Network Connected' 日志的来源,正如您从屏幕截图中看到的那样。

这 2 个 CmdLets 我做错了什么?

我设法使第一个 CmdLet New-WinEvent 工作。奇怪的是这是一个数据类型问题。

'Network Connected' 事件的消息需要 6 个参数。这些参数的预期类型可以在我从 PowerShell

得到的警告中看到

WARNING: Provided payload does not match with the template that was defined for event id 1000. The defined template is following:

我将 Guid 参数作为字符串传递,但它希望它具有 [System.Guid] 类型,显然 New-WinEvent 在传递 6 时不会发出警告数组中 -Payload 参数的参数,即使一个参数没有正确的类型。它只是用一些固定的默认参数创建一个新事件(就像我的问题中发生的那样)。

所以我必须将正确的类型转换为该参数 Guid。我从中得到了它的类型的名称:

$validEvent = (Get-WinEvent -ProviderName Microsoft-Windows-NetworkProfile -MaxEvents 500  | Where-Object {$_.Id -eq 10000} | Where-Object {$_.properties[4].Value -eq 9})[-1]
$validEvent.Properties[2].Value.GetType().FullName

然后我将正确的类型转换为参数并将它们传递给 -Payload 并且它起作用了:

$name = 'SSID'
$desc = 'Description'
[System.Guid]$guid = "c48f86ab-f35d-4f73-a41e-99ea359e1d08"
[System.UInt32]$type = 1
[System.UInt32]$state = 63
[System.UInt32]$categ = 2

New-WinEvent -ProviderName Microsoft-Windows-NetworkProfile -Id 10000 -Payload @($name, $desc, $guid, $type, $state, $categ)

然后我可以更改 $state 的值以从 $newLog.Message.

获取其名称映射

然而,第二个 CmdLet Write-EventLog 没有起作用;显然它不能由同一个提供者写入这个日志。

Max 所述,此 CmdLet 只能写入“经典”事件日志,这就是它无法找到 NetworkProfile 源的原因。

一路上帮助我的一些链接:

by Grady G Cooper

Writing to the event log in .NET - the right way

MSDN - Event Sources

TechNet - New-WinEvent