How to Write an Entry to the Windows Event Log in Batch Script
While logging to a text file is useful for debugging, logging to the Windows Event Log is the industry standard for professional system administration. Event Log entries are persistent, centralized, and can be monitored by enterprise tools like SCOM, Splunk, or Azure Monitor. By writing your script's successes and failures to the Event Log, you ensure that your automation is part of the official system history, making it visible to other administrators and audit trails.
This guide will explain how to use the eventcreate command and PowerShell to log custom messages.
Method 1: Using eventcreate (Built-in Command)
eventcreate is a native Windows utility designed for command-line event logging. It allows you to specify the log name, event type, event ID, and message.
Basic Usage
@echo off
setlocal
:: Verify we have administrative privileges (required for eventcreate)
net session >nul 2>&1
if errorlevel 1 (
echo [ERROR] This script requires administrator privileges. >&2
echo Right-click and select "Run as administrator." >&2
endlocal
exit /b 1
)
:: Write an INFORMATION entry
eventcreate /T INFORMATION /ID 200 /L APPLICATION /SO "BackupScript" ^
/D "Backup script started successfully." >nul
if errorlevel 1 (
echo [ERROR] Failed to write event log entry. >&2
)
:: Write an ERROR entry
eventcreate /T ERROR /ID 900 /L APPLICATION /SO "BackupScript" ^
/D "CRITICAL: Backup failed - insufficient disk space on D: drive." >nul
if errorlevel 1 (
echo [ERROR] Failed to write event log entry. >&2
)
endlocal
exit /b 0
Parameter Breakdown:
| Parameter | Description |
|---|---|
/T [Type] | Event severity: INFORMATION, WARNING, or ERROR |
/ID [N] | A number (1–1000) that identifies this specific event type |
/L [Log] | Which log to write to: APPLICATION or SYSTEM |
/SO [Source] | The source name that identifies your script in Event Viewer |
/D "Text" | The message body for the event entry |
Important notes:
- Administrator privileges are required.
eventcreatewrites to the Windows Event Log, which is a privileged operation. Running as a standard user produces an "Access Denied" error. - Event IDs are limited to 1–1000. Unlike PowerShell (Method 2),
eventcreaterestricts event IDs to this range. - The
/SO(Source) parameter specifies the source name. If omitted,eventcreatedefaults toEventCreateas the source, making it harder to filter your entries in Event Viewer.
Method 2: Using PowerShell (Custom Event Source)
PowerShell provides more flexibility, allowing you to register a custom "Event Source" so your entries appear with a meaningful name in Event Viewer rather than a generic one. This is the preferred approach for scripts that will be deployed across multiple systems.
Step 1: Register the Event Source (One-Time Setup)
Registering a new event source requires administrator privileges and only needs to be done once per machine. After registration, writing events to that source can be done without re-registering.
@echo off
setlocal
set "Source=MyBackupScript"
set "LogName=Application"
:: Check admin rights: source registration requires elevation
net session >nul 2>&1
if errorlevel 1 (
echo [ERROR] Source registration requires administrator privileges. >&2
endlocal
exit /b 1
)
:: Register the source if it does not already exist
powershell -NoProfile -Command ^
"if (-not [System.Diagnostics.EventLog]::SourceExists('%Source%')) {" ^
" New-EventLog -LogName '%LogName%' -Source '%Source%';" ^
" Write-Host 'Event source registered: %Source%'" ^
"} else {" ^
" Write-Host 'Event source already exists: %Source%'" ^
"}"
if errorlevel 1 (
echo [ERROR] Failed to register event source. >&2
endlocal
exit /b 1
)
endlocal
exit /b 0
Step 2: Write Events Using the Registered Source
Once the source is registered, write events using Write-EventLog. This does NOT require re-registering the source.
@echo off
setlocal
set "Source=MyBackupScript"
:: Write an informational event
powershell -NoProfile -Command ^
"Write-EventLog -LogName Application -Source '%Source%'" ^
" -EntryType Information -EventId 200" ^
" -Message 'Data sync completed successfully. 1,247 files processed.'"
if errorlevel 1 (
echo [ERROR] Failed to write event log entry. >&2
endlocal
exit /b 1
)
echo [OK] Event logged.
endlocal
exit /b 0
Why register a custom source?
- Filtering: In Event Viewer, you can filter by Source to see only your script's entries, ignoring thousands of other Application log events.
- Monitoring integration: Enterprise tools (SCOM, Splunk, Zabbix) can create alerts based on specific Source + EventId combinations.
- Professionalism: Events from
MyBackupScriptare immediately identifiable; events from the genericApplicationorEventCreatesource are ambiguous.
Method 3: Integrating Event Logging into a Script
In practice, you want event logging woven into your script's error handling, not as a standalone example. Here is a pattern that logs to both a text file and the Event Log, with a reusable subroutine.
@echo off
setlocal
set "Source=DeployScript"
set "LogFile=%~dp0deploy.log"
:: === Main Logic ===
call :LogEvent INFORMATION 200 "Deployment started on %COMPUTERNAME%."
:: Simulate a task that might fail
if not exist "D:\AppData\" (
call :LogEvent ERROR 900 "Target directory D:\AppData not found. Deployment aborted."
endlocal
exit /b 1
)
call :LogEvent INFORMATION 201 "Target directory verified. Proceeding with file copy."
:: ... (deployment logic here) ...
call :LogEvent INFORMATION 210 "Deployment completed successfully."
endlocal
exit /b 0
:LogEvent
:: Usage: call :LogEvent [Type] [ID] [Message]
:: %~1 = INFORMATION, WARNING, or ERROR
:: %~2 = Event ID number
:: %~3 = Message text
:: Always log to file (works without admin rights)
echo [%date% %time%] [%~1] [ID:%~2] %~3 >> "%LogFile%"
:: Attempt to log to Event Log (may fail without admin rights)
powershell -NoProfile -Command ^
"try {" ^
" Write-EventLog -LogName Application -Source '%Source%'" ^
" -EntryType '%~1' -EventId %~2" ^
" -Message '%~3'" ^
"} catch {" ^
" exit 1" ^
"}" >nul 2>&1
if errorlevel 1 (
echo [%date% %time%] [WARNING] Could not write to Event Log (not elevated?^) >> "%LogFile%"
)
exit /b 0
Why dual logging matters:
- Text log file: Always works, regardless of privileges. Provides a detailed local record with timestamps.
- Event Log: Provides centralized visibility to monitoring tools and other administrators, but requires a registered source and (for
eventcreate) admin rights. - Graceful fallback: If the Event Log write fails (e.g., the source isn't registered or the script isn't elevated), the text log still captures everything.
How to Avoid Common Errors
Wrong Way: Using the Same Event ID for Everything
If you use ID 1 for every message, an administrator cannot filter for "successful backups" vs. "failed backups" in Event Viewer.
Correct Way: Assign meaningful ID ranges to your project:
| ID Range | Purpose |
|---|---|
| 100–199 | Lifecycle events (script start, stop, restart) |
| 200–299 | Success messages (task completed, files copied) |
| 300–399 | Informational warnings (low disk space, slow response) |
| 900–999 | Errors and failures (crash, timeout, missing resource) |
Wrong Way: Using an Unregistered Source with Write-EventLog
:: FAILS: source "MyApp" has never been registered
powershell -Command "Write-EventLog -LogName Application -Source 'MyApp' -EntryType Error -EventId 1 -Message 'Test'"
PowerShell's Write-EventLog requires the source to be registered first with New-EventLog. If the source does not exist, the command throws an error.
Correct Way: Register the source once (see Method 2, Step 1), then write events using that registered source. Or use eventcreate (Method 1), which handles source registration automatically.
Problem: Special Characters in Messages
If your message contains quotes, ampersands, or other special characters, the Batch-to-PowerShell parameter passing can break.
Solution: Keep messages simple, use alphanumeric text, basic punctuation, and avoid embedding file paths with backslashes directly in the message string. If you need to include a file path, use forward slashes or double the backslashes.
Problem: Message Length
The Event Log is designed for concise summaries. If you try to write a very long message (e.g., pasting a multi-page log file), the command may fail or the entry may be truncated.
Solution: Write a short summary to the Event Log (e.g., "Backup failed: disk full on D:") and include the path to a detailed text log file in the message: "Backup failed. See D:\Logs\backup_2024-05-10.log for details."
Best Practices and Rules
1. Verify Your Entries
After writing events, confirm they appear correctly. Open eventvwr.msc (Event Viewer), navigate to Windows Logs > Application, and filter by your Source name or Event ID.
2. Use a Consistent Source Name
Use the same Source name for all events from a given script or project. This allows filtering by Source in Event Viewer to see a chronological timeline of just your script's activity.
3. Log Both Success and Failure
Don't only log errors. Log the script's start, completion, and key milestones. When investigating an incident at 3 AM, knowing that the script started at 2:47 AM but never logged completion tells you exactly when the failure occurred.
4. Fall Back to Text Logging
If your script might run without administrator privileges, always log to a text file as well. The text log serves as a reliable fallback when Event Log writes are denied.
Conclusions
Writing to the Windows Event Log is a foundational step in creating enterprise-ready Batch scripts. By using a registered custom source, meaningful event IDs, and dual logging (Event Log + text file), you make your automation transparent, auditable, and visible to the monitoring infrastructure that professional environments depend on. This practice ensures that your scripts are not isolated files, but integrated components of the Windows operational ecosystem.