How to store an object in the Windows Event Log? How to store an object in the Windows Event Log? powershell powershell

How to store an object in the Windows Event Log?


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.

Method 1: Custom PowerShell Function

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. 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 parametersfunction 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. 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 likeCreateParamEvent 1234 "The server $hostname was logged at $timestamp" $hostname $timestamp 

Method 2: Custom Event Provider

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

enter image description here

  1. Compile the manifest by executing: mc -css Namespace CustomProvider.man

enter image description here

  1. Create the resource file by executing: rc CustomProvider.rc

enter image description here

  1. Compile the source: csc /target:library /unsafe /win32res:CustomProvider.res CustomProvider.cs

enter image description here

  1. Register the provider by executing. wevtutil im CustomProvider.man

enter image description here

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

    enter image description here

  2. 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.

enter image description here

enter image description here