How to resolve the algorithm Write to Windows event log step by step in the AutoHotkey programming language
Published on 12 May 2024 09:40 PM
How to resolve the algorithm Write to Windows event log step by step in the AutoHotkey programming language
Table of Contents
Problem Statement
Write script status to the Windows Event Log
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Write to Windows event log step by step in the AutoHotkey programming language
Source code in the autohotkey programming language
; 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"
LPCtSTRs := 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, A_IsUnicode ? "UTF-16" : "")
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
, LPCtSTRs, &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
}
You may also check:How to resolve the algorithm FizzBuzz step by step in the Zig programming language
You may also check:How to resolve the algorithm Sort stability step by step in the C# programming language
You may also check:How to resolve the algorithm Interactive programming (repl) step by step in the Mathematica / Wolfram Language programming language
You may also check:How to resolve the algorithm Read entire file step by step in the Xtend programming language
You may also check:How to resolve the algorithm Closures/Value capture step by step in the Phix programming language