如何在Windows事件日志中存储对象?

时间:2017-04-24 12:06:09

标签: powershell events logging

最近,我们为所有脚本添加了选项,以便在Windows事件日志中记录其消息。这对于短消息非常有用,但我们似乎无法找到以结构化方式保存事件的方法,以便以后可以使用它们创建对象。

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

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 *

enter image description here

this post中,还有其他选项,但我们似乎无法弄清楚如何正确地做到这一点。

阅读事件是通过以下方式完成的:

'DOMContentLoaded'

感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

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

方法1:自定义PowerShell功能

这种方法来自Kevin Holman撰写的一篇文章,他的解释非常出色。我在这里复制了代码,所以这里的答案将是完整的。

  1. 定义要记录的事件日志和源,加载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))
      }
    
  2. 下一步是设置您要写入日志的参数并调用该函数。

    #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 
    
  3. 方法2:自定义事件提供程序

    这种方法来自Daniel Gordon撰写的一篇文章。我已经减少了他的例子的一些复杂性,并在此GitHub Repository

    中提供了来源和说明。
    1. 您需要提供的关键数据是事件提供程序清单。此清单包含新事件提供程序的详细信息。而且,最重要的是,事件的自定义有效负载。此文件中关键的元素是<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>
      
    2. 创建清单后,我们需要在计算机上编译和安装Provider。我在CustomProvider.man中将我的清单保存为C:\CustomProvider\。如果您不遵循此约定,则必须更新CustomProvider.man中的路径。保存后,以管理员打开Visual Studio命令提示符,然后cd到C:\ CustomProvider

    3. enter image description here

      1. 执行以下操作编译清单:mc -css Namespace CustomProvider.man
      2. enter image description here

        1. 执行:rc CustomProvider.rc
        2. 创建资源文件

          enter image description here

          1. 编译来源:csc /target:library /unsafe /win32res:CustomProvider.res CustomProvider.cs
          2. enter image description here

            1. 通过执行注册提供程序。 wevtutil im CustomProvider.man
            2. enter image description here

              1. 您现在将在Windows事件查看器中看到自定义提供程序

                enter image description here

              2. 要写入日志,请打开Windows Powershell提示并执行New-WinEvent -ProviderName CustomProvider -Id 10000 -Payload @("MyValue1"),然后刷新事件日志,您将看到该事件。

              3. enter image description here

                enter image description here