Jump to content
Sign in to follow this  
mdwerne

How to add multiple lines of EventData to an EventLog?

Recommended Posts

Hello,

I'm working on a script that writes detailed application event logs, and I'd like to know if there is a way with Autoit to write multiple lines of XML EventData (see example below):

 <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
  <System>
  <Provider Name="Application" /> 
  <EventID Qualifiers="0">1001</EventID> 
  <Level>4</Level> 
  <Task>0</Task> 
  <Keywords>0x80000000000000</Keywords> 
  <TimeCreated SystemTime="2015-07-12T21:26:07.000000000Z" /> 
  <EventRecordID>86554</EventRecordID> 
  <Channel>Application</Channel> 
  <Computer>YOUR_COMPUTER</Computer> 
  <Security /> 
  </System>
  <EventData>
     <Data>DeskTop Agent: Mike</Data> 
     <Data>Observer Username: Miguel</Data>
     etc...
  </EventData>
 </Event>

So far, using EventCreate, everything I send end's up in a single <data> entry (see below):

 <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
  <System>
  <Provider Name="Application" /> 
  <EventID Qualifiers="0">1001</EventID> 
  <Level>4</Level> 
  <Task>0</Task> 
  <Keywords>0x80000000000000</Keywords> 
  <TimeCreated SystemTime="2015-07-12T21:26:07.000000000Z" /> 
  <EventRecordID>86554</EventRecordID> 
  <Channel>Application</Channel> 
  <Computer>YOUR_COMPUTER</Computer> 
  <Security /> 
  </System>
  <EventData>
       <Data>DeskTop Agent: Mike Observer Username: Miguel</Data> 
  </EventData>
 </Event>

Here is the code I'm using thus far (which does not work the way I'd like):

$LogData = @CRLF & "DeskTop Agent: " & @UserName & @CRLF & "Observer Username: " & $DTObserver & @CRLF & "File name/s with extension: " & $FilenameWextension & @CRLF & "Action Performed: " & $ActionPerformed & @CRLF & "Explanation: " & $Explanation & @CRLF & "Machine Name: " & @ComputerName & @CRLF & "IP Address: " & @IPAddress1 & @CRLF & "App1Installed: " & $App1 & @CRLF & "App2Installed: " & $App2
Run("eventcreate /T Information /ID 100 /L Application /SO DTALog /D " & Chr(34) & "DTALog Details: " & $LogData & Chr(34), "", @SW_HIDE, 2)

I found a Stackoverflow post that talks about doing it in C# (https://stackoverflow.com/questions/7694276/how-to-add-multiple-lines-of-eventdata-to-an-eventlog-in-windows)
but I'd like to determine if it can be accomplished with AutoIt!.

Thanks for your time,
-Mike

Edited by mdwerne

Share this post


Link to post
Share on other sites

If I use EventCreate using your last snippet and look in Windows Event Viewer, it looks as it should with multiple lines. Evidently, XML strips CRLF from the data. Seems, you could add a pipe "|" in the data where you want a line return and then extract the data from EventData and StringReplace on the pipe. ie: StringReplace($data, '|', @CRLF)

Or perhaps you could add multiple data entries in EventData.

Edited by ripdad

"The mediocre teacher tells. The Good teacher explains. The superior teacher demonstrates. The great teacher inspires." -William Arthur Ward

Share this post


Link to post
Share on other sites

Thanks for the reply ripdad!

So I must be missing something in what your trying to tell me. I changed my last snippet to this:

$LogData = @CRLF & "DeskTop Agent: " & @UserName & "|" & "Observer Username: " & $DTObserver & "|" & "File name/s with extension: " & $FilenameWextension & "|" & "Action Performed: " & $ActionPerformed & "|" & "Explanation: " & $Explanation & "|" & "Machine Name: " & @ComputerName & "|" & "IP Address: " & @IPAddress1 & "|" & "App1Installed: " & $App1 & "|" & "App2Installed: " & $App2
Run("eventcreate /T Information /ID 100 /L Application /SO DTALog /D " & Chr(34) & "DTALog Details: " & $LogData & Chr(34), "", @SW_HIDE, 2)

and when generated, the event looked like this:

- <EventData>
  <Data>DTALog Details: DeskTop Agent: mike|Observer Username: miguel|File name/s with extension: 10|Action Performed: e.g. Copied project documents from C: drive to F: (USB Drive)|Explanation: e.g. To allow work on project document from another workstation.|Machine Name: R123456|IP Address: 192.168.0.1|App1Installed: 1|App2Installed: 1</Data> 
  </EventData>

I am using Splunk to query the event logs, and would like each of the variables in their own <data> field. Like this:

<EventData>
  <Data>Data Transfer Agent: mike</Data> 
  <Data>Observer Username: miguel</Data> 
  <Data>File name/s with extension: 10</Data> 
  <Data>Action Performed: e.g. Copied project documents from C: drive to F: (USB Drive)</Data> 
  <Data>Explanation: e.g. To allow work on project document from another workstation</Data> 
  <Data>Machine Name: R123456</Data> 
  <Data>IP Address: 192.168.0.1</Data> 
  <Data>App1Installed: 1</Data> 
  <Data>App2Installed: 1</Data> 
  </EventData>

I'm not sure how I would do this using the suggestion you gave me.

I've also tried this method, with no additional success.

#include <EventLog.au3>

Example()

Func Example()
    Local $hEventLog, $aData[4] = [3, 1, 2, 3]

    $hEventLog = _EventLog__Open("", "Application")
    _EventLog__Report($hEventLog, 4, 0, 2, "Administrator", "AutoIt3 generated event", $aData)
    _EventLog__Close($hEventLog)
EndFunc   ;==>Example

Thanks again,
-Mike

Share this post


Link to post
Share on other sites
19 minutes ago, mdwerne said:

I am using Splunk to query the event logs, and would like each of the variables in their own <data> field. Like this:

<EventData>
  <Data>Data Transfer Agent: mike</Data> 
  <Data>Observer Username: miguel</Data> 
  <Data>File name/s with extension: 10</Data> 
  <Data>Action Performed: e.g. Copied project documents from C: drive to F: (USB Drive)</Data> 
  <Data>Explanation: e.g. To allow work on project document from another workstation</Data> 
  <Data>Machine Name: R123456</Data> 
  <Data>IP Address: 192.168.0.1</Data> 
  <Data>App1Installed: 1</Data> 
  <Data>App2Installed: 1</Data> 
  </EventData>

 

 

I was thinking more like this...

<EventData>
  <Data1>Data Transfer Agent: mike</Data1> 
  <Data2>Observer Username: miguel</Data2> 
  <Data3>File name/s with extension: 10</Data3> 
</EventData>

I don't know much about XML, but it seems logical.

 


"The mediocre teacher tells. The Good teacher explains. The superior teacher demonstrates. The great teacher inspires." -William Arthur Ward

Share this post


Link to post
Share on other sites

This would work for me as well...the question is still how. :(

Above you suggested "Or perhaps you could add multiple data entries in EventData."

EventCreate does not like more than 1 of the /D switch, and I'm not sure how to use the "_EventLog__Report" function to add multiple data entries...if it's even possible.

If I look through my Application Event log, I see that other apps can create entries like I'm after:

- <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
- <System>
  <Provider Name="Application Error" /> 
  <EventID Qualifiers="0">1000</EventID> 
  <Level>2</Level> 
  <Task>100</Task> 
  <Keywords>0x80000000000000</Keywords> 
  <TimeCreated SystemTime="2017-12-04T22:02:33.393707600Z" /> 
  <EventRecordID>10493</EventRecordID> 
  <Channel>Application</Channel> 
  <Computer>R123456.my.domain</Computer> 
  <Security /> 
  </System>
- <EventData>
  <Data>consent.exe</Data> 
  <Data>10.0.15063.0</Data> 
  <Data>e0f856c4</Data> 
  <Data>unknown</Data> 
  <Data>0.0.0.0</Data> 
  <Data>00000000</Data> 
  <Data>c0000409</Data> 
  <Data>0000000000000000</Data> 
  <Data>f8c</Data> 
  <Data>01d36d4b962f1993</Data> 
  <Data>c:\windows\system32\consent.exe</Data> 
  <Data>unknown</Data> 
  <Data>01cbf734-c21e-46ce-8132-df9596bb70f4</Data> 
  <Data /> 
  <Data /> 
  </EventData>
  </Event>

maybe I need to jump over to C# for this project.

Thanks for the suggestions nonetheless,
-Mike

Share this post


Link to post
Share on other sites

This is the first time I heard of Splunk, so i have no idea how it handles data.

Although, any text can be manipulated...

Opt('MustDeclareVars', 1)

Local $s = "Data Transfer Agent: mike|Observer Username: miguel|File name/s with extension: 10"
Local $a = StringSplit($s, '|')
$s = '<EventData>' & @CRLF

For $i = 1 To $a[0]
    $s &= '    <Data' & $i & '>' & $a[$i] & '</Data' & $i & '>' & @CRLF
Next

$s &= '</EventData>'
MsgBox(0, 'Result', $s)

After that, it's a matter of replacing that section in the XML -- since that seems to be the format you want it in.

 


"The mediocre teacher tells. The Good teacher explains. The superior teacher demonstrates. The great teacher inspires." -William Arthur Ward

Share this post


Link to post
Share on other sites

Sadly, this is how it shows up in the event log:

- <EventData>
  <Data>DTALog Details: <EventData> <Data1>Data Transfer Agent: mike</Data1> <Data2>Observer Username: miguel</Data2> <Data3>File name/s with extension: 10</Data3> </EventData></Data> 
  </EventData>

While it may not be obvious from the snippet above, the $s variable came in as plain text, not actual XML data.

Thanks for giving it a shot...I'll see if there is another way to go about this.

Share this post


Link to post
Share on other sites
9 minutes ago, mdwerne said:

Sadly, this is how it shows up in the event log:


- <EventData>
  <Data>DTALog Details: <EventData> <Data1>Data Transfer Agent: mike</Data1> <Data2>Observer Username: miguel</Data2> <Data3>File name/s with extension: 10</Data3> </EventData></Data> 
  </EventData>

I didn't mean that you run that with EventCreate, but after you have the resulting XML file. Read it in AutoIt, then work from there. Here's another way to manipulate it -- if you don't care about the data numbers...

Local $s = "Data Transfer Agent: mike|Observer Username: miguel|File name/s with extension: 10|"
$s = '<EventData>' & @CRLF & '<Data>' & StringReplace($s, '|', '</Data>' & @CRLF & '<Data>')
$s = StringTrimRight($s, 6) & '</EventData>'
$s = StringReplace($s, '<Data>', '    <Data>')
MsgBox(0, 'Result', $s)

 


"The mediocre teacher tells. The Good teacher explains. The superior teacher demonstrates. The great teacher inspires." -William Arthur Ward

Share this post


Link to post
Share on other sites

So, I got it worked out as simple as I could -- unless you find a better solution...

Opt('MustDeclareVars', 1)

; read the xml
Local $sFile = FileRead(@ScriptDir & '\EventOriginal.xml')

; load it in array
Local $a = StringSplit($sFile, @CRLF, 1)

Local $s = ''

; loop through fields
For $i = 1 To $a[0]
    If StringInStr($a[$i], '<Data>') Then
        ; manipulate the data
        $a[$i] = '    ' & StringStripWS($a[$i], 3)
        $a[$i] = StringReplace($a[$i], '|', '</Data>' & @CRLF & '    <Data>')
    EndIf
    ; re-assemble 
    $s &= $a[$i] & @CRLF
Next

MsgBox(0, 'Final Result', $s)

; write final result to file
Local $hFile = FileOpen(@ScriptDir & '\EventResult.xml', 2)
FileWrite($hFile, $s)
FileClose($hFile)

Here is the xml file I worked with, which has pipes denoting where returns should go...

EventOriginal.xml

 

Edited by ripdad

"The mediocre teacher tells. The Good teacher explains. The superior teacher demonstrates. The great teacher inspires." -William Arthur Ward

Share this post


Link to post
Share on other sites

Hi, Mdwerne,

I have the same question and problem here by writing event data with XML format... (Multiple lines)

still not understand how to use the array Data...

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By nacerbaaziz
      hello autoit team
      please i need your help today
      am trying to make the list of features in list view and control it
      am using the dism command line to read output
      i've made the code
      but i found some problems
      what i need is the list of features in 2d array
      $array[$n][0]= name $array[$i][1] = state
      when i tested the code
      it give me some results that i don't need to it e.g
      ------ ------  | --------
      or
      name       | state
      i need just the list of features and there state
      please help me to do that
      here is my example
      #RequireAdmin #NoTrayIcon #include <AutoItConstants.au3> Wow64EnableWow64FsRedirection(false) _Windows_Get_Features() func _Windows_Get_Features() local $a_FeaturesArray[1][2] $a_FeaturesArray[0][0] local $i_Dism_Run = Run("DISM /online /english /get-features /format:table", "", @sw_hide, BitOR($STDERR_CHILD, $STDOUT_CHILD)) local $s_OutputDism = "", $a_OutPutDism While 1 $s_OutputDism = StdoutRead($i_Dism_Run) If @error Then exitLoop if ($s_OutputDism = "") or (StringRegExp($s_OutputDism, "^((\-){1,})?(?:\s)\|?(?:\s)((\-){1,})$", 0) = 1) then ContinueLoop if (StringRegExp($s_OutputDism, "((([\s\d\-\+\_\,]{1})\|([\s\d\-\+\_\,]{1})){1,})", 0) = 1) then $a_OutPutDism = StringSplit($s_OutputDism, @lf) for $i = 1 to $a_OutPutDism[0] if msgBox(1, $i, $a_OutPutDism[$i]) = 1 then exitLoop next endIf Wend endFunc func Wow64EnableWow64FsRedirection($b_Enabled) local $h_OpenFS = DLLOpen("kernel32.dll") local $Return = DllCall($h_OpenFS, "boolean", "Wow64EnableWow64FsRedirection", "boolean", $b_Enabled) if @error then DLLClose($h_OpenFS) Return SetError(@error, @extended, -1) else DLLClose($h_OpenFS) Return $Return[0] endIf endFunc  
    • By nacerbaaziz
      question about _WinAPI_CreateWindowEx
      good morning
      welcome autoit team
      please i need your help
      i've searched a lot about how to use the _WinAPI_CreateWindowEx
      finally i found an example
      but i found some problem i hope you can help me
      firstly, i want to set the controls focussable with the keyboard input
      i already used the ws_tabStop but it did not work with me.
      secondly, i want to set some access keys linked with the window
      such as control+o enable the open button and control+f4 exit the app
      note: i need a local access keys and not a global hotkeys
      such as GUISetAccelerators
      finaly, before i will put the code here i must clarify a few things.
      1. you will ask me why you don't use the GUICreate function
      here i'll tell you that it as dialog and It is a little heavy in motion with screen readers.
      the screen readers for blind has some function that work with dialogs and others work with full windows style
      2. you will ask me why you didn't search the net for that?
      i will tell you that all examples that i found in the internet with pdfs and Picture books.
      i found some examples in microsoft but it with cpp.
      ok here is the code
      i hope you can help me to do what i want
      thank you in advance
       
      ; Small AutoIt Application that uses Windows API ; Written by Yuraj #NoTrayIcon #include <_RegisterClassEx.au3> #include <WinAPI.au3> #include <WindowsConstants.au3> #include <ButtonConstants.au3> #include <EditConstants.au3> #include <FontConstants.au3> AutoItSetOption("MustDeclareVars", 1) ; Window definitions Const $WinWidth = 370 Const $WinHeight = 350 Const $WinXPos = (@DesktopWidth / 2) - ($WinWidth / 2) Const $WinYPos = (@DesktopHeight / 2) - ($WinHeight / 2) Const $WinTitle = "Win32 Application - Text reader" Const $WinClass = "mainapp" Const $WinIcon = _WinAPI_LoadIcon(_WinAPI_GetModuleHandle("shell32.dll"), 13) ; Windows handles Global $hwnd, $edit1, $btn1, $btn2 ; Fonts Global $fnt1 ; Register class, Create the window Local $retVal = __WinAPI_RegisterClassEx($WinClass, "WindowCallback", $WinIcon, 0, _WinAPI_GetSysColor($COLOR_BTNFACE), BitOR($CS_DEFAULTSTYLE, $CS_DROPSHADOW)) ; If $retVal == 0 Then ; If registerclass fails MsgBox(16, "Error", "Error while registering window class!") Exit EndIf ; Create windows/controls $hwnd = _WinAPI_CreateWindowEx($WS_EX_STATICEDGE, $WinClass, $WinTitle, BitOR($WS_OVERLAPPED,$WS_SYSMENU, $WS_MINIMIZEBOX, $WS_GROUP, $WS_DLGFRAME), $WinXPos, $WinYPos, $WinWidth, $WinHeight, 0) $btn1 = _WinAPI_CreateWindowEx(0, "button", "Open file ...", BitOR($WS_VISIBLE, $WS_CHILD, $WS_TABSTOP, $WS_CLIPCHILDREN), 25, 270, 100, 30,$hwnd) $btn2 = _WinAPI_CreateWindowEx(0, "Button", "Exit", BitOR($WS_VISIBLE, $WS_CHILD, $WS_TABSTOP, $WS_CLIPCHILDREN), 235, 270, 100, 30, $hwnd) $edit1 = _WinAPI_CreateWindowEx(0, "edit", "text", BitOR($WS_VISIBLE, $WS_CHILD, $WS_VSCROLL, $ES_AUTOVSCROLL, $es_readOnly, $WS_TABSTOP), 5, 5, $WinWidth - 15, $WinHeight - 100, $hwnd) ; Set controls identifiers _WinAPI_SetWindowLong($btn1,$GWL_ID,150) _WinAPI_SetWindowLong($btn2,$GWL_ID,160) ; Set (controls) fonts $fnt1 = _CreateFont("MS Sans Serif", 15) _WinAPI_SetFont($btn1, $fnt1) _WinAPI_SetFont($btn2, $fnt1) _WinAPI_SetFont($edit1, $fnt1) ; Set focus to edit _WinAPI_SetFocus($edit1) ; Show window _WinAPI_ShowWindow($hwnd) _WinAPI_UpdateWindow($hwnd) ; Main loop that keep application opened While 1 Sleep(100) WEnd ;=================================================================; ; WINDOW CALLBACK ... ;=================================================================; Func WindowCallback($_hwnd, $iMsg, $wParam, $lParam) Local $iNC, $iID Switch $iMsg ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Case $WM_CLOSE ; Show message on closing If MsgBox(48 + 4, $WinTitle, "Do you want really exit?", 0, $hwnd) <> 6 Then Return 0 ; Call destructor and then exit main thread FinalizeApp() Exit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Case $WM_COMMAND $iNC = _WinAPI_HiWord($wParam) $iID = _WinAPI_LoWord($lParam) Switch $iNC Case $BN_CLICKED ; When is control clicked Switch _WinAPI_GetDlgCtrlID($iID) Case _WinAPI_GetDlgCtrlID($btn1) BtnOpenFileClick() Case _WinAPI_GetDlgCtrlID($btn2) BtnExitClick() EndSwitch EndSwitch ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; EndSwitch Return _WinAPI_DefWindowProc($_hwnd, $iMsg, $wParam, $lParam) EndFunc ;==>WindowCallback Func FinalizeApp() _WinAPI_DeleteObject($fnt1) _WinAPI_DestroyWindow($hwnd) __WinAPI_UnregisterClass($WinClass) EndFunc ;==>FinalizeApp Func _CreateFont($fontName, $height = 16, $style = $FW_NORMAL, $italic = False, $underline = False, $strikeout = False) Local $hFont = _WinAPI_CreateFont($height, 0, 0, 0, $style, $italic, $underline, $strikeout, $DEFAULT_CHARSET, _ $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $DEFAULT_QUALITY, $DEFAULT_PITCH, $fontName) Return $hFont EndFunc ;==>_CreateFont ;=================================================================; ; WINDOW EVENTS ;=================================================================; Func BtnOpenFileClick() Local $ret = _WinAPI_GetOpenFileName("", "Text files (*.txt)|All files (*.*)", ".", "", "", 1, 0, 0, $hwnd) If ($ret[0] > 0) Then Local $path = $ret[1] & "\" & $ret[2] Local $file = _WinAPI_CreateFile($path, 2, 2) Local $buf = DllStructCreate("byte[" & _WinAPI_GetFileSizeEx($file) & "]") Local $i = 0 _WinAPI_ReadFile($file, DllStructGetPtr($buf), _WinAPI_GetFileSizeEx($file), $i) ; Close file handle _WinAPI_CloseHandle($file) _WinAPI_SetWindowText($edit1, BinaryToString(DllStructGetData($buf, 1))) EndIf EndFunc ;==>BtnOpenFileClick Func BtnExitClick() FinalizeApp() Exit EndFunc ;==>BtnExitClick  
      _RegisterClassEx.au3
    • By Saravanan2213
      Hi everyone,
      i just need your help. i have script for cleaning browsing history and other unwanted file but the problem is i don't want to see the GUI i have attached below. It should not show anything on the screen. is it possible to do it in autoit. thanks in advance.
       
      So for i have tried flag
      Run("rundll32.exe InetCpl.cpl,ClearMyTracksByProcess 255", "", @SW_HIDE)
      @SW_DISABLE
       
      Looking forward your help.........

    • By Kelvin44
      WiFi Disconnects Automatically Windows 10 / 8 / 7 Laptop. This video guide very help to me
    • By PeterVerbeek
      Hi Guys,
      I've noticed that the SoundGetWaveVolume UDF in an older topic isn't working on Windows Vista, 7, 8, 8.1 and 10. It's probably a Windows XP UDF. The UDF below does work. It successfully returns the volume set by SoundSetWaveVolume. It might need checking by the AutoIt community for some synthax finetuning.
      ; #FUNCTION# ==================================================================================================================== ; Name...........: _SoundGetWaveVolume ; Description....: Returns app volume of script, Windows Vista, 7, 8, 10 only ; Syntax.........: _SoundGetWaveVolume([$iValueOnError = -1]) ; Parameters.....: $iValueOnError - Value to return when an error occurs ; Return values..: App volume of script or $iValueOnError at an error ; Error values...: @error = 1 - Unable to create Struct ; @error = 2 - Dll file not found ; @error = 3 - Wrong call so not on Windows Vista, 7, 8 or 10 ; @error = 4 - Internal error, array not returned ; @error = 5 - Volume wasn't received ; @error = 6 - Volume couldn't read ; Author.........: Peter Verbeek ; Modified.......: ; =============================================================================================================================== Func _SoundGetWaveVolume($iValueOnError = -1) Local $LPDWORD,$aMMRESULT,$iVolume $LPDWORD = DllStructCreate("dword") If @error <> 0 Then SetError(1) ; 1 = unable to create Struct Return $iValueOnError EndIf ; get app volume of this script $aMMRESULT = DllCall("winmm.dll","uint","waveOutGetVolume","ptr",0,"long_ptr",DllStructGetPtr($LPDWORD)) Switch @error Case 1 SetError(2) ; 2 = dll file not found Return $iValueOnError Case 2,3,4,5 SetError(3) ; 3 = wrong call so not on Windows Vista, 7, 8 or 10 Return $iValueOnError EndSwitch If not IsArray($aMMRESULT) Then SetError(4) ; 4 = internal error, array not returned Return $iValueOnError EndIf If $aMMRESULT[0] <> 0 Then SetError(5) ; 5 = volume wasn't received Return $iValueOnError EndIf $iVolume = DllStructGetData($LPDWORD,1) If @error <> 0 Then SetError(6) ; 6 = volume couldn't read Return $iValueOnError EndIf Return Round(100*$iVolume/4294967295) ; return in range 0 to 100 as SoundSetWaveVolume() EndFunc  
×
×
  • Create New...