Write to Windows event log: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎{{header|REXX}}: removed STYLE from the PRE html tag.)
(Added Batch File)
Line 193: Line 193:
return char_count
return char_count
}</lang>
}</lang>

=={{header|Batch File}}==
The "EventCreate" command does the task.
<lang>@echo off
EventCreate /t ERROR /id 123 /l SYSTEM /so "A Batch File" /d "This is found in system log."
EventCreate /t WARNING /id 456 /l APPLICATION /so BlaBla /d "This is found in apps log"
</lang>
{{Out}}
<pre>>EventLog.BAT

SUCCESS: An event of type 'ERROR' was created in the 'SYSTEM' log with 'A Batch File' as the source.

SUCCESS: An event of type 'WARNING' was created in the 'APPLICATION' log with 'BlaBla' as the source.

></pre>
If you do not want the command to display its result or errors...
<lang>@echo off
EventCreate /t ERROR /id 123 /l SYSTEM /so "A Batch File" /d "This is found in system log." 2>NUL>NUL
EventCreate /t WARNING /id 456 /l APPLICATION /so BlaBla /d "This is found in apps log" 2>NUL>NUL
::That "2>NUL>NUL" trick actually works in any command!</lang>


=={{header|BBC BASIC}}==
=={{header|BBC BASIC}}==

Revision as of 15:00, 23 June 2015

Task
Write to Windows event log
You are encouraged to solve this task according to the task description, using any language you may know.

Write script status to the Windows Event Log

AutoHotkey

<lang autohotkey>; By ABCza, http://www.autohotkey.com/board/topic/76170-function-send-windows-log-events/ h := RegisterForEvents("AutoHotkey") SendWinLogEvent(h, "Test Message") DeregisterForEvents(h)

/*


FUNCTION: SendWinLogEvent


Writes an entry at the end of the specified Windows event log. Returns nonzero if the function succeeds or zero if it fails.

PARAMETERS: ~~~~~~~~~~~ hSource - Handle to a previously registered events source with RegisterForEvents. evType - EVENTLOG_SUCCESS := 0x0000 EVENTLOG_AUDIT_FAILURE := 0x0010 EVENTLOG_AUDIT_SUCCESS := 0x0008 EVENTLOG_ERROR_TYPE := 0x0001 EVENTLOG_INFORMATION_TYPE := 0x0004 EVENTLOG_WARNING_TYPE := 0x0002 evId - Event ID, can be any dword value. evCat - Any value, used to organize events in categories. pStrings - A continuation section with newline separated strings (each max 31839 chars). pData - A buffer containing the binary data.


SYSTEM CALLS, STRUCTURES AND INFO:


ReportEvent - http://msdn.microsoft.com/en-us/library/windows/desktop/aa363679(v=vs.85).aspx Event Identifiers - http://msdn.microsoft.com/en-us/library/windows/desktop/aa363651(v=vs.85).aspx Event categories - http://msdn.microsoft.com/en-us/library/windows/desktop/aa363649(v=vs.85).aspx


  • /

SendWinLogEvent(hSource, String="", evType=0x0004, evId=0x03EA, evCat=0, pData=0) { Ptr := A_PtrSize ? "Ptr" : "UInt" StringPut := A_IsUnicode ? "StrPut" : "StrPut2"

; Reserve and initialise space for the event message. VarSetCapacity(eventMessage, StrLen(String), 0) %StringPut%(String, eventMessage)

r := DllCall("Advapi32.dll\ReportEvent" (A_IsUnicode ? "W" : "A") , UInt, hSource ; handle , UShort, evType ; WORD, eventlog_information_type , UShort, evCat ; WORD, category , UInt, evId ; DWORD, event ID, 0x03EA , Ptr, 0 ; PSID, ptr to user security ID , UShort, 1 ; WORD, number of strings , UInt, VarSetCapacity(pData) ; DWORD, data size , Ptr, &eventMessage ; LPCTSTR*, ptr to a buffer ... , Ptr, (VarSetCapacity(pData)) ? &pData : 0 ) ; ptr to a buffer of binary data

; Release memory. VarSetCapacity(eventMessage, 0)

Return r } /*


FUNCTION: RegisterForEvents


Registers the application to send Windows log events. Returns a handle to the registered source.

PARAMETERS: ~~~~~~~~~~~ logName - Can be "Application", "System" or a custom log name.


SYSTEM CALLS, STRUCTURES AND INFO:


RegisterEventSource - http://msdn.microsoft.com/en-us/library/windows/desktop/aa363678(v=VS.85).aspx Event Sources - http://msdn.microsoft.com/en-us/library/windows/desktop/aa363661(v=VS.85).aspx


  • /

RegisterForEvents(logName) { Return DllCall("Advapi32.dll\RegisterEventSource" (A_IsUnicode ? "W" : "A") , UInt, 0 ; LPCTSTR, Local computer , Str, logName) ; LPCTSTR Source name } /*


FUNCTION: DeregisterForEvents


Deregisters the previously registered application.

PARAMETERS: ~~~~~~~~~~~ hSource - Handle to a registered source.


SYSTEM CALLS, STRUCTURES AND INFO:


DeregisterEventSource - http://msdn.microsoft.com/en-us/library/windows/desktop/aa363642(v=vs.85).aspx Event Sources - http://msdn.microsoft.com/en-us/library/windows/desktop/aa363661(v=VS.85).aspx


  • /

DeregisterForEvents(hSource) { IfNotEqual, hSource, 0, Return DllCall( "Advapi32.dll\DeregisterEventSource" , UInt, hSource ) }

StrPut for AutoHotkey Basic

StrPut2(String, Address="", Length=-1, Encoding=0) { ; Flexible parameter handling: if Address is not integer  ; StrPut(String [, Encoding]) Encoding := Address, Length := 0, Address := 1024 else if Length is not integer  ; StrPut(String, Address, Encoding) Encoding := Length, Length := -1

; Check for obvious errors. if (Address+0 < 1024) return

; Ensure 'Encoding' contains a numeric identifier. if Encoding = UTF-16 Encoding = 1200 else if Encoding = UTF-8 Encoding = 65001 else if SubStr(Encoding,1,2)="CP" Encoding := SubStr(Encoding,3)

if !Encoding ; "" or 0 { ; No conversion required. char_count := StrLen(String) + 1 ; + 1 because generally a null-terminator is wanted. if (Length) { ; Check for sufficient buffer space. if (StrLen(String) <= Length || Length == -1) { if (StrLen(String) == Length) ; Exceptional case: caller doesn't want a null-terminator. char_count-- ; Copy the string, including null-terminator if requested. DllCall("RtlMoveMemory", "uint", Address, "uint", &String, "uint", char_count) } else ; For consistency with the sections below, don't truncate the string. char_count = 0 } ;else: Caller just wants the the required buffer size (char_count), which will be returned below. } else if Encoding = 1200 ; UTF-16 { ; See the 'else' to this 'if' below for comments. if (Length <= 0) { char_count := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, "uint", &String, "int", StrLen(String), "uint", 0, "int", 0) + 1 if (Length == 0) return char_count Length := char_count } char_count := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, "uint", &String, "int", StrLen(String), "uint", Address, "int", Length) if (char_count && char_count < Length) NumPut(0, Address+0, char_count++*2, "UShort") } else if Encoding is integer { ; Convert native ANSI string to UTF-16 first. NOTE - wbuf_len includes the null-terminator. VarSetCapacity(wbuf, 2 * wbuf_len := StrPut2(String, "UTF-16")), StrPut2(String, &wbuf, "UTF-16")

; UTF-8 and some other encodings do not support this flag. Avoid it for UTF-8 ; (which is probably common) and rely on the fallback behaviour for other encodings. flags := Encoding=65001 ? 0 : 0x400 ; WC_NO_BEST_FIT_CHARS if (Length <= 0) ; -1 or 0 { ; Determine required buffer size. loop 2 { char_count := DllCall("WideCharToMultiByte", "uint", Encoding, "uint", flags, "uint", &wbuf, "int", wbuf_len, "uint", 0, "int", 0, "uint", 0, "uint", 0) if (char_count || A_LastError != 1004) ; ERROR_INVALID_FLAGS break flags := 0 ; Try again without WC_NO_BEST_FIT_CHARS. } if (!char_count) return ; FAIL if (Length == 0) ; Caller just wants the required buffer size. return char_count ; Assume there is sufficient buffer space and hope for the best: Length := char_count } ; Convert to target encoding. char_count := DllCall("WideCharToMultiByte", "uint", Encoding, "uint", flags, "uint", &wbuf, "int", wbuf_len, "uint", Address, "int", Length, "uint", 0, "uint", 0) ; Since above did not null-terminate, check for buffer space and null-terminate if there's room. ; It is tempting to always null-terminate (potentially replacing the last byte of data), ; but that would exclude this function as a means to copy a string into a fixed-length array. if (char_count && char_count < Length) NumPut(0, Address+0, char_count++, "Char") ; else no space to null-terminate; or conversion failed. } ; Return the number of characters copied. return char_count }</lang>

Batch File

The "EventCreate" command does the task. <lang>@echo off EventCreate /t ERROR /id 123 /l SYSTEM /so "A Batch File" /d "This is found in system log." EventCreate /t WARNING /id 456 /l APPLICATION /so BlaBla /d "This is found in apps log" </lang>

Output:
>EventLog.BAT

SUCCESS: An event of type 'ERROR' was created in the 'SYSTEM' log with 'A Batch File' as the source.

SUCCESS: An event of type 'WARNING' was created in the 'APPLICATION' log with 'BlaBla' as the source.

>

If you do not want the command to display its result or errors... <lang>@echo off EventCreate /t ERROR /id 123 /l SYSTEM /so "A Batch File" /d "This is found in system log." 2>NUL>NUL EventCreate /t WARNING /id 456 /l APPLICATION /so BlaBla /d "This is found in apps log" 2>NUL>NUL

That "2>NUL>NUL" trick actually works in any command!</lang>

BBC BASIC

Writes to the Application Log: <lang bbcbasic> INSTALL @lib$+"COMLIB"

     PROC_cominitlcid(1033)
     
     WshShell% = FN_createobject("WScript.Shell")
     PROC_callmethod(WshShell%, "LogEvent(0, ""Test from BBC BASIC"")")
     
     PROC_releaseobject(WshShell%)
     PROC_comexit</lang>

C#

In Windows Vista and later or Windows Server 2003, you must have administrative privileges to execute this code. <lang csharp>using System.Diagnostics;

namespace RC {

 internal class Program
 {
   public static void Main()
   {
     string sSource  = "Sample App";
     string sLog     = "Application";
     string sEvent   = "Hello from RC!";
     if (!EventLog.SourceExists(sSource))
       EventLog.CreateEventSource(sSource, sLog);
     EventLog.WriteEntry(sSource, sEvent);
     EventLog.WriteEntry(sSource, sEvent, EventLogEntryType.Information);
   }
 }

}</lang>

Clojure

<lang clojure>(use 'clojure.java.shell) (sh "eventcreate" "/T" "INFORMATION" "/ID" "123" "/D" "Rosetta Code example")</lang>

Delphi

<lang Delphi>program WriteToEventLog;

{$APPTYPE CONSOLE}

uses Windows;

procedure WriteLog(aMsg: string); var

 lHandle: THandle;
 lMessagePtr: Pointer;

begin

 lMessagePtr := PChar(aMsg);
 lHandle := RegisterEventSource(nil, 'Logger');
 if lHandle > 0 then
 begin
   try
     ReportEvent(lHandle, 4 {Information}, 0, 0, nil, 1, 0, @lMessagePtr, nil);
   finally
     DeregisterEventSource(lHandle);
   end;
 end;

end;

begin

 WriteLog('Message to log.');

end.</lang>

PicoLisp

PicoLisp doesn't run on Windows. In case of Linux, the equivalent of the event log is the syslog. It can be written with 'native' C functions, or simply with the 'logger' utility: <lang PicoLisp>: (call 'logger "This is a test") -> T

(call 'logger "This" 'is "another" 'test)

-> T</lang>

PureBasic

<lang PureBasic>Procedure WriteToLog(Event_App$,EventMessage$,EvenetType,Computer$)

 Protected wNumStrings.w, lpString=@EventMessage$, lReturnX, CMessageTyp, lparray
 Protected lprawdata=@EventMessage$, rawdata=Len(EventMessage$), Result
 Protected lLogAPIRetVal.l = RegisterEventSource_(Computer$, Event_App$)
 If lLogAPIRetVal
   lReturnX = ReportEvent_(lLogAPIRetVal,EvenetType,0,CMessageTyp,0,wNumStrings,rawdata,lparray,lprawdata
   DeregisterEventSource_(lLogAPIRetVal)
   Result=#True
 EndIf
 ProcedureReturn Result

EndProcedure</lang>

PowerShell

<lang powershell># Create Event Log object $EventLog=new-object System.Diagnostics.EventLog("Application")

  1. Declare Event Source; must be 'registered' with Windows

$EventLog.Source="Application" # It is possible to register a new source (see Note2)

  1. Setup the Event Types; you don't have to use them all, but I'm including all the possibilities for reference

$infoEvent=[System.Diagnostics.EventLogEntryType]::Information $errorEvent=[System.Diagnostics.EventLogEntryType]::Error $warningEvent=[System.Diagnostics.EventLogEntryType]::Warning $successAuditEvent=[System.Diagnostics.EventLogEntryType]::SuccessAudit $failureAuditEvent=[System.Diagnostics.EventLogEntryType]::FailureAudit

  1. Write the event in the format "Event test",EventType,EventID

$EventLog.WriteEntry("My Test Event",$infoevent,70)</lang> Note1: Thanks to PoSH Fan for posting information that got me started on this at Windows PowerShell Blog
Note2: See details on registering a new Event Source with Windows at MSDN

Python

Library: PyWin32

<lang Python>import win32api import win32con import win32evtlog import win32security import win32evtlogutil

ph = win32api.GetCurrentProcess() th = win32security.OpenProcessToken(ph, win32con.TOKEN_READ) my_sid = win32security.GetTokenInformation(th, win32security.TokenUser)[0]

applicationName = "My Application" eventID = 1 category = 5 # Shell myType = win32evtlog.EVENTLOG_WARNING_TYPE descr = ["A warning", "An even more dire warning"] data = "Application\0Data".encode("ascii")

win32evtlogutil.ReportEvent(applicationName, eventID, eventCategory=category, eventType=myType, strings=descr, data=data, sid=my_sid)</lang>

Racket

Racket's logging facility creates windows events when running on Windows.

<lang Racket>

  1. lang racket

(log-warning "Warning: nothing went wrong.") </lang>

REXX

This was executed on a (Microsoft) Windows/XP PRO system. <lang rexx>/*REXX program writes a "record" (event) to the (MS) Windows event log.*/

   eCMD = 'EVENTCREATE'
   type = 'INFORMATION'         /*one of:  ERROR  WARNING  INFORMATION */
     id =  234                  /*in range:  1 ───►  1000  (inclusive).*/
logName = 'APPLICATION'
 source = 'REXX'
   desc = 'attempting to add an entry for Rosetta Code demonstration.'
   desc = '"' || desc '"'       /*enclose DESCription in double quotes.*/

eCMD '/T' type "/ID" id '/L' logName "/SO" source '/D' desc

                                /*stick a fork in it honey, we're done.*/</lang>

output

SUCCESS: A 'INFORMATION' type event is created in the 'REXX' log/source.

Ruby

Library: win32-utils

<lang ruby>require 'win32/eventlog' logger = Win32::EventLog.new logger.report_event(:event_type => Win32::EventLog::INFO, :data => "a test event log entry")</lang>

Instructions on setting up an Event Source is here

Tcl

Library: TWAPI

<lang tcl>package require twapi

  1. This command handles everything; use “-type error” to write an error message

twapi::eventlog_log "My Test Event" -type info</lang>

zkl

Translation of: Clojure

<lang zkl>zkl: System.cmd(0'|eventcreate "/T" "INFORMATION" "/ID" "123" "/D" "Rosetta Code example"|)</lang>

Output:
SUCCESS: A 'INFORMATION' type event is created in the 'EventCreate' log/source.
0