Write to Windows event log
You are encouraged to solve this task according to the task description, using any language you may know.
- Task
Write script status to the Windows Event Log
11l[edit]
:start:
I :argv.len != 5
print(‘Usage : #. < Followed by level, id, source string and description>’.format(:argv[0]))
E
os:(‘EventCreate /t #. /id #. /l APPLICATION /so #. /d "#."’.format(:argv[1], :argv[2], :argv[3], :argv[4]))
AutoHotkey[edit]
; 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
}
AWK[edit]
# syntax: GAWK -f WRITE_TO_WINDOWS_EVENT_LOG.AWK
BEGIN {
write("INFORMATION",1,"Rosetta Code")
exit (errors == 0) ? 0 : 1
}
function write(type,id,description, cmd,esf) {
esf = errors # errors so far
cmd = sprintf("EVENTCREATE.EXE /T %s /ID %d /D \"%s\" >NUL",type,id,description)
printf("%s\n",cmd)
if (toupper(type) !~ /^(SUCCESS|ERROR|WARNING|INFORMATION)$/) { error("/T is invalid") }
if (id+0 < 1 || id+0 > 1000) { error("/ID is invalid") }
if (description == "") { error("/D is invalid") }
if (errors == esf) {
system(cmd)
}
return(errors)
}
function error(message) { printf("error: %s\n",message) ; errors++ }
- Output:
EVENTCREATE.EXE /T INFORMATION /ID 1 /D "Rosetta Code" >NUL
Batch File[edit]
The "EventCreate" command does the task.
@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"
- 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...
@echo off
EventCreate /t ERROR /id 123 /l SYSTEM /so "A Batch File" /d "This is found in system log." >NUL 2>&1
EventCreate /t WARNING /id 456 /l APPLICATION /so BlaBla /d "This is found in apps log" >NUL 2>&1
::That ">NUL 2>&1" trick actually works in any command!
NOTE: This will (...or might) not work if you do not have administrator privileges.
BBC BASIC[edit]
Writes to the Application Log:
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
C[edit]
The following is a wrapper on the EventCreate utility provided in Windows. Note that to use this wrapper, the code must be executed from a console/IDE running as Administrator. The utility itself does extensive error-checking and validation, so apart from the check that 5 arguments have been supplied, no other validations or checks are performed.
#include<stdlib.h>
#include<stdio.h>
int main(int argC,char* argV[])
{
char str[1000];
if(argC!=5)
printf("Usage : %s < Followed by level, id, source string and description>",argV[0]);
else{
sprintf(str,"EventCreate /t %s /id %s /l APPLICATION /so %s /d \"%s\"",argV[1],argV[2],argV[3],argV[4]);
system(str);
}
return 0;
}
Invocation and output on console :
C:\rosettaCode>eventLog.exe WARNING 458 SOmeString "This is a joke" SUCCESS: An event of type 'WARNING' was created in the 'APPLICATION' log with 'SOmeString' as the source.
Microsoft does provide an C/C++ API for EventCreate, but as with everything Microsoft, it's so wonderfully convoluted, that I will just give a link to the ReportEvent example.
C#[edit]
In Windows Vista and later or Windows Server 2003, you must have administrative privileges to execute this code.
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);
}
}
}
C++[edit]
#include <iostream>
#include <sstream>
int main(int argc, char *argv[]) {
using namespace std;
#if _WIN32
if (argc != 5) {
cout << "Usage : " << argv[0] << " (type) (id) (source string) (description>)\n";
cout << " Valid types: SUCCESS, ERROR, WARNING, INFORMATION\n";
} else {
stringstream ss;
ss << "EventCreate /t " << argv[1] << " /id " << argv[2] << " /l APPLICATION /so " << argv[3] << " /d \"" << argv[4] << "\"";
system(ss.str().c_str());
}
#else
cout << "Not implemented for *nix, only windows.\n";
#endif
return 0;
}
Clojure[edit]
(use 'clojure.java.shell)
(sh "eventcreate" "/T" "INFORMATION" "/ID" "123" "/D" "Rosetta Code example")
D[edit]
import std.process;
import std.stdio;
void main() {
auto cmd = executeShell(`EventCreate /t INFORMATION /id 123 /l APPLICATION /so Dlang /d "Rosetta Code Example"`);
if (cmd.status == 0) {
writeln("Output: ", cmd.output);
} else {
writeln("Failed to execute command, status=", cmd.status);
}
}
Delphi[edit]
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.
F#[edit]
Bare bone writing to the Application Eventlog giving no event-ID and using the default event type (information.)
use log = new System.Diagnostics.EventLog()
log.Source <- "Sample Application"
log.WriteEntry("Entered something in the Application Eventlog!")
Go[edit]
This works on Windows 10 with administrative privileges.
package main
import (
"fmt"
"os/exec"
)
func main() {
command := "EventCreate"
args := []string{"/T", "INFORMATION", "/ID", "123", "/L", "APPLICATION",
"/SO", "Go", "/D", "\"Rosetta Code Example\""}
cmd := exec.Command(command, args...)
err := cmd.Run()
if err != nil {
fmt.Println(err)
}
}
Java[edit]
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
public class WriteToWindowsEventLog {
public static void main(String[] args) throws IOException, InterruptedException {
String osName = System.getProperty("os.name").toUpperCase(Locale.ENGLISH);
if (!osName.startsWith("WINDOWS")) {
System.err.println("Not windows");
return;
}
Process process = Runtime.getRuntime().exec("EventCreate /t INFORMATION /id 123 /l APPLICATION /so Java /d \"Rosetta Code Example\"");
process.waitFor(10, TimeUnit.SECONDS);
int exitValue = process.exitValue();
System.out.printf("Process exited with value %d\n", exitValue);
if (exitValue != 0) {
InputStream errorStream = process.getErrorStream();
String result = new BufferedReader(new InputStreamReader(errorStream))
.lines()
.collect(Collectors.joining("\n"));
System.err.println(result);
}
}
}
Julia[edit]
Run as an administrator.
cmd = "eventcreate /T INFORMATION /ID 123 /D \"Rosetta Code Write to Windows event log task example\""
Base.run(`$cmd`)
Kotlin[edit]
The following works on Windows 10 with administrative privileges:
// version 1.1.4-3
fun main(args: Array<String>) {
val command = "EventCreate" +
" /t INFORMATION" +
" /id 123" +
" /l APPLICATION" +
" /so Kotlin" +
" /d \"Rosetta Code Example\""
Runtime.getRuntime().exec(command)
}
Lingo[edit]
shell = xtra("Shell").new()
props = [:]
props["operation"] = "runas"
props["parameters"] = "/t INFORMATION /id 123 /l APPLICATION /so Lingo /d ""E&"Rosetta Code Example""E
shell.shell_exec("EventCreate", props)
Perl[edit]
The Win32::EventLog module has the Report method to write in the EventLog
use strict;
use warnings;
use Win32::EventLog;
my $handle = Win32::EventLog->new("Application");
my $event = {
Computer => $ENV{COMPUTERNAME},
Source => 'Rosettacode',
EventType => EVENTLOG_INFORMATION_TYPE,
Category => 'test',
EventID => 0,
Data => 'a test for rosettacode',
Strings => 'a string test for rosettacode',
};
$handle->Report($event);
Phix[edit]
The first two lines are of course entirely optional, but could help prevent someone/a newbie from wasting their time trying to achieve the impossible.
requires(WINDOWS) -- (as in this will not work on Linux or p2js, duh) without js -- (as above, also prevent pointless attempts to transpile) system(`eventcreate /T INFORMATION /ID 123 /D "Rosetta Code Write to Windows event log task example"`)
- Output:
SUCCESS: An event of type 'INFORMATION' was created in the 'Application' log with 'EventCreate' as the source.
PicoLisp[edit]
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:
: (call 'logger "This is a test")
-> T
: (call 'logger "This" 'is "another" 'test)
-> T
PowerShell[edit]
# 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)
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
Source and event log existing[edit]
$MessageFreeLula = 'Global unions and union leaders from more than 50 countries came together ' +
'in Geneva today to stand in solidarity with former Brazilian President Lula, calling for ' +
'his immediate release from jail and that he be allowed to run in the upcoming elections.'
Write-EventLog -LogName 'System' -Source 'Eventlog' -Message $MessageFreeLula -EventId 13 -EntryType 'Information'
'SUCCESS: The Lula Livre message (#FreeLula) has been recorded in the system log event.'
- output:
SUCCESS: The Lula Livre message (#FreeLula) has been recorded in the system log event.
New event log[edit]
$MessageFreeLula = 'Global unions and union leaders from more than 50 countries came together ' +
'in Geneva today to stand in solidarity with former Brazilian President Lula, calling for ' +
'his immediate release from jail and that he be allowed to run in the upcoming elections.'
New-EventLog -LogName 'Free Lula!' -Source '#FreeLula'
Limit-EventLog -OverflowAction 'OverWriteAsNeeded' -MaximumSize (64KB*13) -LogName 'Free Lula!'
Write-EventLog -LogName 'Free Lula!' -Source '#FreeLula' -Message $MessageFreeLula -EventId 13 -EntryType 'Information'
'SUCCESS: The Lula Livre message (#FreeLula) has been recorded in the "Free Lula!" log event.'
- output:
SUCCESS: The Lula Livre message (#FreeLula) has been recorded in the "Free Lula!" log event.
PureBasic[edit]
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
Python[edit]
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)
Racket[edit]
Racket's logging facility creates windows events when running on Windows.
#lang racket
(log-warning "Warning: nothing went wrong.")
Raku[edit]
(formerly Perl 6)
There is not yet (that I am aware of) a native interface to the Windows logging functions, but Raku can shell out and run a console command just as easily as most of these other languages. It does have a native interface to the syslog functions under POSIX environments though.
(Same caveats as the others, needs to be run as administrator or with elevated privileges under Windows.)
given $*DISTRO {
when .is-win {
my $cmd = "eventcreate /T INFORMATION /ID 123 /D \"Bla de bla bla bla\"";
run($cmd);
}
default { # most POSIX environments
use Log::Syslog::Native;
my $logger = Log::Syslog::Native.new(facility => Log::Syslog::Native::User);
$logger.info("[$*PROGRAM-NAME pid=$*PID user=$*USER] Just thought you might like to know.");
}
}
REXX[edit]
This was executed on a (Microsoft) Windows/XP PRO system.
annotated[edit]
/*REXX program writes a "record" (event) to the (Microsoft) Windows event log. */
eCMD = 'EVENTCREATE' /*name of the command that'll be used. */
type = 'INFORMATION' /*one of: ERROR WARNING INFORMATION */
id = 234 /*in range: 1 ───► 1000 (inclusive).*/
logName = 'APPLICATION' /*information about what this is. */
source = 'REXX' /* " " who's doing this. */
desc = 'attempting to add an entry for a 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, we're all done. */
- output:
SUCCESS: A 'INFORMATION' type event is created in the 'REXX' log/source.
bare bones[edit]
/*REXX program writes a "record" (event) to the (Microsoft) Windows event log. */
/* [↓] cmd options have extra spacing.*/
'EVENTCREATE /T INFORMATION /ID 234 /L APPLICATION /SO REXX' ,
'/D "attempting to add an entry for a Rosetta Code demonstration."'
/*stick a fork in it, we're all done. */
- output is identical to the 1st REXX version.
Ruby[edit]
require 'win32/eventlog'
logger = Win32::EventLog.new
logger.report_event(:event_type => Win32::EventLog::INFO, :data => "a test event log entry")
Instructions on setting up an Event Source is here
Rust[edit]
#[cfg(windows)]
mod bindings {
::windows::include_bindings!();
}
#[cfg(windows)]
use bindings::{
Windows::Win32::Security::{
GetTokenInformation, OpenProcessToken, PSID, TOKEN_ACCESS_MASK, TOKEN_INFORMATION_CLASS,
TOKEN_USER,
},
Windows::Win32::SystemServices::{
GetCurrentProcess, OpenEventLogA, ReportEventA, ReportEvent_wType, HANDLE, PSTR,
},
};
#[cfg(windows)]
fn main() -> windows::Result<()> {
let ph = unsafe { GetCurrentProcess() };
let mut th: HANDLE = HANDLE(0);
unsafe { OpenProcessToken(ph, TOKEN_ACCESS_MASK::TOKEN_QUERY, &mut th) }.ok()?;
// Determine the required buffer size, ignore ERROR_INSUFFICIENT_BUFFER
let mut length = 0_u32;
unsafe {
GetTokenInformation(
th,
TOKEN_INFORMATION_CLASS::TokenUser,
std::ptr::null_mut(),
0,
&mut length,
)
}
.ok()
.unwrap_err();
// Retrieve the user token.
let mut token_user_bytes = vec![0u8; length as usize];
unsafe {
GetTokenInformation(
th,
TOKEN_INFORMATION_CLASS::TokenUser,
token_user_bytes.as_mut_ptr().cast(),
length,
&mut length,
)
}
.ok()?;
// Extract the pointer to the user SID.
let user_sid: PSID = unsafe { (*token_user_bytes.as_ptr().cast::<TOKEN_USER>()).User.Sid };
// use the Application event log
let event_log_handle = unsafe { OpenEventLogA(PSTR::default(), "Application") };
let mut event_msg = PSTR(b"Hello in the event log\0".as_ptr() as _);
unsafe {
ReportEventA(
HANDLE(event_log_handle.0), //h_event_log: T0__,
ReportEvent_wType::EVENTLOG_WARNING_TYPE, // for type use EVENTLOG_WARNING_TYPE w_type: u16,
5, // for category use "Shell" w_category: u16,
1, // for ID use 1 dw_event_id: u32,
user_sid, // lp_user_sid: *mut c_void,
1, // w_num_strings: u16,
0, // dw_data_size: u32,
&mut event_msg, // lp_strings: *mut PSTR,
std::ptr::null_mut(), // lp_raw_data: *mut c_void,
)
}
.ok()?;
Ok(())
}
#[cfg(not(windows))]
fn main() {
println!("Not implemented");
}
add this to the build.rs:
fn main() {
#[cfg(windows)]
{
windows::build!(Windows::Win32::SystemServices::{GetCurrentProcess, ReportEventA, OpenEventLogA, ReportEvent_wType, HANDLE, PSTR},
Windows::Win32::Security::{OpenProcessToken, GetTokenInformation, TOKEN_ACCESS_MASK, TOKEN_INFORMATION_CLASS, TOKEN_USER, PSID});
}
}
And this to cargo.toml:
[target.'cfg(windows)'.dependencies]
windows = "0.7.0"
[target.'cfg(windows)'.build-dependencies]
windows = "0.7.0"
Scala[edit]
The following works on Windows 10 with elevated (administrative) permission:
object RegisterWinLogEvent extends App {
import sys.process._
def eventCreate= Seq("EVENTCREATE", "/T", "SUCCESS", "/id", "123", "/l", "APPLICATION", "/so", "Scala RegisterWinLogEvent", "/d", "Rosetta Code Example" ).!!
println(eventCreate)
println(s"\nSuccessfully completed without errors. [total ${scala.compat.Platform.currentTime - executionStart} ms]")
}
Standard ML[edit]
From bsd/linux/unix to log
OS.Process.system "logger \"Log event\" " ;
From MS Windows to MS Windows, taken from C:
OS.Process.system "EventCreate /t WARNING /id 458 /l APPLICATION /so SomeSource /d \"Settastring\"" ;
Tcl[edit]
package require twapi
# This command handles everything; use “-type error” to write an error message
twapi::eventlog_log "My Test Event" -type info
VBScript[edit]
Sub write_event(event_type,msg)
Set objShell = CreateObject("WScript.Shell")
Select Case event_type
Case "SUCCESS"
n = 0
Case "ERROR"
n = 1
Case "WARNING"
n = 2
Case "INFORMATION"
n = 4
Case "AUDIT_SUCCESS"
n = 8
Case "AUDIT_FAILURE"
n = 16
End Select
objShell.LogEvent n, msg
Set objShell = Nothing
End Sub
Call write_event("INFORMATION","This is a test information.")
Wren[edit]
This embedded program is untested as I no longer have a working Windows machine but should work when run with administrative privileges - what can possibly go wrong?
/* write_to_windows_event_log.wren */
class Windows {
foreign static eventCreate(args)
}
var args = [
"/T", "INFORMATION", "/ID", "123", "/L", "APPLICATION",
"/SO", "Wren", "/D", "\"Rosetta Code Example\""
].join(" ")
Windows.eventCreate(args)
Now embed this script in the following C program, compile and run it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wren.h"
/* C <=> Wren interface functions */
void C_eventCreate(WrenVM* vm) {
const char *args = wrenGetSlotString(vm, 1);
char command[strlen(args) + 13];
strcpy(command, "EventCreate ");
strcat(command, args);
system(command);
}
WrenForeignMethodFn bindForeignMethod(
WrenVM* vm,
const char* module,
const char* className,
bool isStatic,
const char* signature) {
if (strcmp(module, "main") == 0) {
if (strcmp(className, "Windows") == 0) {
if (isStatic && strcmp(signature, "eventCreate(_)") == 0) return C_eventCreate;
}
}
return NULL;
}
static void writeFn(WrenVM* vm, const char* text) {
printf("%s", text);
}
void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {
switch (errorType) {
case WREN_ERROR_COMPILE:
printf("[%s line %d] [Error] %s\n", module, line, msg);
break;
case WREN_ERROR_STACK_TRACE:
printf("[%s line %d] in %s\n", module, line, msg);
break;
case WREN_ERROR_RUNTIME:
printf("[Runtime Error] %s\n", msg);
break;
}
}
char *readFile(const char *fileName) {
FILE *f = fopen(fileName, "r");
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
rewind(f);
char *script = malloc(fsize + 1);
fread(script, 1, fsize, f);
fclose(f);
script[fsize] = 0;
return script;
}
int main(int argc, char **argv) {
WrenConfiguration config;
wrenInitConfiguration(&config);
config.writeFn = &writeFn;
config.errorFn = &errorFn;
config.bindForeignMethodFn = &bindForeignMethod;
WrenVM* vm = wrenNewVM(&config);
const char* module = "main";
const char* fileName = "write_to_windows_event_log.wren";
char *script = readFile(fileName);
WrenInterpretResult result = wrenInterpret(vm, module, script);
switch (result) {
case WREN_RESULT_COMPILE_ERROR:
printf("Compile Error!\n");
break;
case WREN_RESULT_RUNTIME_ERROR:
printf("Runtime Error!\n");
break;
case WREN_RESULT_SUCCESS:
break;
}
wrenFreeVM(vm);
free(script);
return 0;
}
zkl[edit]
zkl: System.cmd(0'|eventcreate "/T" "INFORMATION" "/ID" "123" "/D" "Rosetta Code example"|)
- Output:
SUCCESS: A 'INFORMATION' type event is created in the 'EventCreate' log/source. 0
- Pages with syntax highlighting errors
- Programming Tasks
- Solutions by Programming Task
- 11l
- AutoHotkey
- AWK
- Batch File
- BBC BASIC
- C
- C sharp
- C++
- Clojure
- D
- Delphi
- F Sharp
- Go
- Java
- Julia
- Kotlin
- Lingo
- Shell xtra
- Perl
- Win32::EventLog
- Phix
- PicoLisp
- PowerShell
- PureBasic
- Python
- PyWin32
- Racket
- Raku
- REXX
- Ruby
- Win32-utils
- Rust
- Scala
- Standard ML
- Tcl
- TWAPI
- VBScript
- Wren
- Zkl
- 6502 Assembly/Omit
- 68000 Assembly/Omit
- Lotus 123 Macro Scripting/Omit
- Mathematica/Omit
- Maxima/Omit
- MIPS Assembly/Omit
- PARI/GP/Omit
- PostScript/Omit
- Retro/Omit
- TI-83 BASIC/Omit
- Z80 Assembly/Omit
- Zkl/Omit
- ZX Spectrum Basic/Omit