如何在Windows事件日志中存储对象? [英] How to store an object in the Windows Event Log?

查看:65
本文介绍了如何在Windows事件日志中存储对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近,我们已将选项添加到所有脚本中,以将其消息记录在Windows事件日志中.这对于短消息非常有用,但是我们似乎找不到一种以结构化方式保存事件的方法,因此我们以后可以用它们创建对象.

Recently we've added the option to all our scripts to log their messages in the Windows Event Log. This works great for short messages, but we can't seem to find a way to save events in a structured way so we can later create objects with them.

可以存储多个对象属性的事件的示例:

An example of an event that can store multiple object proprties:

如何使用PowerShell完成此操作?

How is this done with PowerShell?

我们已经按照这里,但没有运气:

We've tried the following as described here but with no luck:

Write-EventLog -LogName HCScripts -Source 'Test (Brecht)' -EventId 4 -Message "<Data Name=""MyKey1"">MyValue1</Data>"

In this post there are other options described but we can't seem to figure out how to do it properly.

通过以下方式读取事件:

Reading the events is done with:

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 *

谢谢您的帮助.

推荐答案

我发现了两个问题"PowerShell如何完成?"的可能解决方案.第一个涉及自定义PowerShell方法,并利用系统程序集写入事件日志.第二个涉及实现自定义提供程序.请注意,这不会在<Data>节点中存储XML.它将数据存储在独立的元素中.

I have found two possible solutions to the question "How is this done with PowerShell?". The first involves a custom PowerShell method and utilizing system assemblies to write to an event log. The second involves implementing a custom provider. It should be noted, this doesn't store XML in the <Data> node. It stores data in independent elements.

方法1:自定义PowerShell功能

此方法来自凯文·霍尔曼(Kevin Holman)他的解释非常出色.我在这里复制了代码,所以这里的答案将是完整的.

This methodology comes form an article written by Kevin Holman His explanation is outstanding. I duplicated the code here so the answer here will be complete.

  1. 也定义事件日志和您想要记录的源,加载System.Diagnostics.EventLog程序集,最后创建一个函数CreateParamEvent,该函数将使用特定参数写入事件日志.

  1. Define the event log and source you want to log too, load the System.Diagnostics.EventLog assembly, and finally create a function CreateParamEvent that will write to an event log with specific parameters.

#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))
  }

  • 下一步是设置要写入日志的参数并调用该函数.

  • The next step is to setup the parameters you'd like to write to the log and call the function.

    #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 我降低了他的示例的复杂性,并在此

    This methodology comes form an article written by Daniel Gordon I've reduced some of the complexity of his example and provided source and instructions in this GitHub Repository

    1. 您需要提供的关键数据是事件提供程序清单.此清单包含新事件提供程序的详细信息.而且,最重要的是,事件的自定义有效负载.此文件中至关重要的元素是<templates>元素.它定义了最终将在事件有效负载中变成<Data>元素的字段.
    1. The key piece of data you need to provide is an Event Provider Manifest. This manifest contains the details of the new event provider. And, most importantly, the custom payload of the event. The element in this file that is critical is the <templates> element. It defines the fields that will ultimately turn into <Data> elements in your event payload.

        <?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>
    

    1. 创建清单后,我们需要在计算机上编译并安装Provider.我在C:\CustomProvider\中将清单保存为CustomProvider.man.如果不遵循此约定,则必须更新CustomProvider.man中的路径.保存后,以 Administrator 身份打开Visual Studio命令提示符,并CD到C:\ CustomProvider
    1. Once the manifest is created, we need to compile and install the Provider on the computer. I saved my manifest as CustomProvider.man in C:\CustomProvider\. If you don't follow this convention, you'll have to update the paths in the CustomProvider.man. Once saved, Open a Visual Studio Command Prompt as Administrator and cd to C:\CustomProvider

    1. 通过执行以下命令来编译清单:mc -css Namespace CustomProvider.man

    1. 执行以下命令来创建资源文件:rc CustomProvider.rc

    1. 编译源代码:csc /target:library /unsafe /win32res:CustomProvider.res CustomProvider.cs

    1. 通过执行注册提供者. wevtutil im CustomProvider.man

    1. 您现在将在Windows Event Viewer中看到自定义提供程序

    1. You'll now see the custom provider in the Windows Event Viewer

    要写入日志,请打开Windows Powershell提示符并执行

    To write to the log, open a Windows Powershell prompt and execute

    New-WinEvent -ProviderName CustomProvider -Id 10000 -Payload @("MyValue1") 
    

    然后刷新事件日志,您将看到事件.

    then refresh the event log and you'll see the event.

    这篇关于如何在Windows事件日志中存储对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆