Write to Windows event log: Difference between revisions
Added zkl |
Adds Clojure solution |
||
Line 228:
}
}</lang>
=={{header|Clojure}}==
<lang clojure>(use 'clojure.java.shell)
(sh "eventcreate" "/T" "INFORMATION" "/ID" "123" "/D" "Rosetta Code example")</lang>
=={{header|Delphi}}==
|
Revision as of 21:41, 9 August 2014
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>
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")
- Declare Event Source; must be 'registered' with Windows
$EventLog.Source="Application" # It is possible to register a new source (see Note2)
- 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
- 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
<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>
- 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
<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
<lang tcl>package require twapi
- This command handles everything; use “-type error” to write an error message
twapi::eventlog_log "My Test Event" -type info</lang>