最近,我们为所有脚本添加了选项,以便在Windows事件日志中记录其消息。这对于短消息非常有用,但我们似乎无法找到以结构化方式保存事件的方法,以便以后可以使用它们创建对象。
PowerShell如何完成?
我们已按照here所述尝试了以下内容,但没有运气:
Function Get-WinEventDataHC {
Param (
[Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
[System.Diagnostics.Eventing.Reader.EventLogRecord[]]$Event
)
Process {
foreach ($E in $Event){
$XML = [XML]$E.ToXml()
# Some events use other nodes, like 'UserData' on Applocker events...
$XMLData = $null
if ($XMLData = @($XML.Event.EventData.Data)){
For ($i=0; $i -lt $XMLData.count; $i++){
$Params = @{
InputObject = $E
NotePropertyName = $EventXML.Event.EventData.Data[$i].Name
NotePropertyValue = $EventXML.Event.EventData.Data[$i].’#text’
}
Add-Member @Params
}
}
$E
}
}
}
Get-WinEvent -ProviderName 'Test (Brecht)' | Select-Object -First 1 | Get-WinEventDataHC | fl *
在this post中,还有其他选项,但我们似乎无法弄清楚如何正确地做到这一点。
阅读事件是通过以下方式完成的:
'DOMContentLoaded'
感谢您的帮助。
答案 0 :(得分:2)
我找到了两个可能的解决方案,问题是“如何使用PowerShell完成这项工作?”。第一种方法涉及自定义PowerShell方法,并利用系统程序集写入事件日志。第二个涉及实现自定义提供程序。应该注意,这不会在<Data>
节点中存储XML。它将数据存储在独立元素中。
方法1:自定义PowerShell功能
这种方法来自Kevin Holman撰写的一篇文章,他的解释非常出色。我在这里复制了代码,所以这里的答案将是完整的。
定义要记录的事件日志和源,加载System.Diagnostics.EventLog
程序集,最后创建一个函数CreateParamEvent
,该函数将写入具有特定参数的事件日志。
#Define the event log and your custom event source
$evtlog = "Application"
$source = "MyEventSource"
#Load the event source to the log if not already loaded. This will fail if the event source is already assigned to a different log.
if ([System.Diagnostics.EventLog]::SourceExists($source) -eq $false) {
[System.Diagnostics.EventLog]::CreateEventSource($source, $evtlog)
}
#function to create the events with parameters
function CreateParamEvent ($evtID, $param1, $param2, $param3)
{
$id = New-Object System.Diagnostics.EventInstance($evtID,1); #INFORMATION EVENT
#$id = New-Object System.Diagnostics.EventInstance($evtID,1,2); #WARNING EVENT
#$id = New-Object System.Diagnostics.EventInstance($evtID,1,1); #ERROR EVENT
$evtObject = New-Object System.Diagnostics.EventLog;
$evtObject.Log = $evtlog;
$evtObject.Source = $source;
$evtObject.WriteEvent($id, @($param1,$param2,$param3))
}
下一步是设置您要写入日志的参数并调用该函数。
#These are just examples to pass as parameters to the event
$hostname = "computername.domain.net"
$timestamp = (get-date)
#Command line to call the function and pass whatever you like
CreateParamEvent 1234 "The server $hostname was logged at $timestamp" $hostname $timestamp
方法2:自定义事件提供程序
这种方法来自Daniel Gordon撰写的一篇文章。我已经减少了他的例子的一些复杂性,并在此GitHub Repository
中提供了来源和说明。您需要提供的关键数据是事件提供程序清单。此清单包含新事件提供程序的详细信息。而且,最重要的是,事件的自定义有效负载。此文件中关键的元素是<templates>
元素。它定义了最终将变为事件有效负载中<Data>
个元素的字段。
<?xml version="1.0" encoding="UTF-8"?>
<instrumentationManifest xsi:schemaLocation="http://schemas.microsoft.com/win/2004/08/events eventman.xsd"
xmlns="http://schemas.microsoft.com/win/2004/08/events"
xmlns:win="http://manifests.microsoft.com/win/2004/08/windows/events"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:trace="http://schemas.microsoft.com/win/2004/08/events/trace">
<instrumentation>
<events>
<provider name="CustomProvider"
symbol="CustomProvider"
guid="{10ABB82A-BB5A-45FF-A7D6-D7369B235DD8}"
resourceFileName="C:\CustomProvider\CustomProvider.dll"
messageFileName="C:\CustomProvider\CustomProvider.dll">
<events>
<event symbol="CustomEvent" value="10000" version="1" channel="CustomProvider/Log" template="CustomTemplate" />
</events>
<levels/>
<tasks/>
<opcodes/>
<channels>
<channel name="CustomProvider/Log" value="0x10" type="Operational" enabled="true" />
</channels>
<templates>
<template tid="CustomTemplate">
<data name="MyKey1" inType="win:UnicodeString" outType="xs:string" />
</template>
</templates>
</provider>
</events>
</instrumentation>
<localization/>
</instrumentationManifest>
创建清单后,我们需要在计算机上编译和安装Provider。我在CustomProvider.man
中将我的清单保存为C:\CustomProvider\
。如果您不遵循此约定,则必须更新CustomProvider.man
中的路径。保存后,以管理员打开Visual Studio命令提示符,然后cd到C:\ CustomProvider
mc -css Namespace CustomProvider.man
rc CustomProvider.rc