Checking event entries/writing to event log only once - c#

How do i read the last entered event log or is there any other way to limit to write only once the same event? This piece of code will help, but is there any other approach available?
EventLog eventLog;
eventLog = new EventLog();
eventLog.Log = eventLogName;
eventLog.Source = sourceName;
foreach (EventLogEntry log in eventLog.Entries)
{
//log.Source - do your stuff
}

There is an excellent article on Reading and Writing to the Event Log.
Use the Entries member when reading from the event log.
Because the property is read-only, you cannot modify an entry or write
to the log using Entries. Instead, specify a Source and call
WriteEntry to write a new log entry. You can use Entries to count the
number of entries in the event log, and view each EventLogEntry in the
collection. Use the indexed Item member to retrieve information about
a specific entry, such as Message, Category, TimeWritten, or
EntryType.
It is not necessary to specify a Source when only reading from a log.
You can specify only the Log name and MachineName (server computer
name) properties for the EventLog instance. In either case, the
Entries member is automatically populated with the event log's list of
entries. You can select the appropriate index for an item in this list
to read individual entries.
An important distinction between reading and writing log entries is
that it is not necessary to explicitly call a read method. After the
Log and MachineName are specified, the Entries property is
automatically populated. If you change the value of the Log or
MachineName property, the Entries property is repopulated the next
time you read it.
An example would be:
using System;
using System.Diagnostics;
class MySample{
public static void Main(){
EventLog myLog = new EventLog();
myLog.Log = "MyNewLog";
foreach(EventLogEntry entry in myLog.Entries){
Console.WriteLine("\tEntry: " + entry.Message);
}
}
}
You'll obviously want to create a method that will be able to filter or sort out your request based on certain criteria to help limit your choices. Hopefully this helps.
You may encounter certain permission issues; as they are tied into an Administrator Category with the EventLogPermissionAccess.Administer.
The information provided is directly from Microsoft here.

Related

Message read by OnEntryWritten are coming with parameters not set

I'm using the OnEntryWritten event in order to get events from the event log when they are fired.
The problem I started to see today is that some messages come with parameters unset.
For example:
The Windows Filtering Platform has permitted a bind to a local port. Application Information: Process ID:9852 Application Name:\device\harddiskvolume7\program files (x86)\google\chrome\application\chrome.exe Network Information: Source Address::: Source Port:51714 Protocol:17 Filter Information: Filter Run-Time ID:0 Layer Name:%%14608 Layer Run-Time ID:38
You can see the %%14608 parameter. This comes with a value if I see the same log in the Event Viewer.
I'm running a windows service as LocalSystem, so I don't know if this is a permission issue or this technology is not useful at all.
I have tried the rest offered on C# and they also don't meet my requirements.
UPDATE: this is the code I'm using to read the events.
1) First I subscribe to the corresponding Event log:
private void Subscribe()
{
_eventLog.EnableRaisingEvents = true;
var callbackFunction = new EntryWrittenEventHandler(OnEntryWritten);
_eventLog.EntryWritten += callbackFunction;
// Save a reference for callbackFunction
_eventHandler = callbackFunction;
}
2) Then on the callback method, I read data from the message:
public void OnEntryWritten(Object source, EntryWrittenEventArgs entryArgs)
{
// When overwrite policy is enabled, this will trigger for all elements when it starts writing new ones
try
{
var entry = entryArgs.Entry;
var timeWritten = entry.TimeWritten;
// This comes with %% values depending on the log
string message = entry.Message;
}
catch(Exception ex)
{
...
}
}
3) The event log variable is simply initialized as:
var eventLog = EventLog.GetEventLogs().FirstOrDefault(el => el.Log.Equals(logName, StringComparison.OrdinalIgnoreCase));
I need some help on this, honestly I don't know what else to try.
UPDATE
I'm adding some images here so everybody can understand the situation a little bit better. To be honest, it looks like there's no solution but to implement a dictionary and replace manually the required values, which appear to be always constants.
This is what I see on the Event Viewer for a given Event ID:
This is what I see on my program when I read that entry:
You can clearly see that the following values:
"Machine key." (Key type)
"Read persisted key from file." (Operation)
Are coming unmapped in the ReplacementStrings and the Message properties as: %%2499 and %%2458
This is the message value I get on the program:
"Key file operation.\r\n\r\nSubject:\r\n\tSecurity ID:\t\tS-1-5-18\r\n\tAccount Name:\t\tMyAccount$\r\n\tAccount Domain:\t\tWORKGROUP\r\n\tLogon ID:\t\t0x3e7\r\n\r\nProcess Information:\r\n\tProcess ID:\t\t6644\r\n\tProcess Creation Time:\t2019-04-03T12:17:24.587994400Z\r\n\r\nCryptographic Parameters:\r\n\tProvider Name:\tMicrosoft Software Key Storage Provider\r\n\tAlgorithm Name:\tUNKNOWN\r\n\tKey Name:\t816339d2-c476-4f1e-bc40-954f0aa0f851\r\n\tKey Type:\t%%2499\r\n\r\nKey File Operation Information:\r\n\tFile Path:\tC:\ProgramData\Microsoft\Crypto\Keys\6d55a45fd69327293e9ed3e7930f4565_5663a8bb-2d1d-4c0d-90c1-624beddabe9c\r\n\tOperation:\t%%2458\r\n\tReturn Code:\t0x0"
What can be done here? There also nothing in entry.Data that might help me out to obtain both values.
No, I believe you're mistaken, sorry that this answer is too late. I found a similar event that was raised by chrome and evaluated if there's anything missed by the event handler. There wasn't anything missed. The message I got in my console output exactly matched what I saw in my Event Viewer.
A better solution would be to
Use entry.Data to get the complete data instead of entry.Message
entry.Data will return a byte[] which you can convert to a string. Here's the link to all properties that an entry will have.

Remove one event from eventlog (or cast EventRecord to EventLogEntry)

My code sifts through events from a remote PC to test whether there are some 6008 (unexpected reboot) events.
I'm using code like:
EventLog log = new EventLog("System",remoteMachine);
EventLogEntryCollection entries = log.Entries;
var entries_filtered = entries.Cast<EventLogEntry>().Where (x => x.EventID=6008);
foreach (EventLogEntry entry in entries) {//my logic here}
During the process, I don't like the way that every event is logged ('reading event'), and so I've come up with two solutions:
Find a way to delete events with some features, so I can delete my
reading events
Before reading, copy the evtx file and read event from this file.
But in this case, I need to use something like:
EventLogReader elr = new EventLogReader("C:\\myevents.evtx");
EventRecord a = elr.ReadEvent();
I need to find a way to cast the EventRecord to a EventLogEntry or the EventReader to a EventLogEntryCollection to remove the need to change the entire logic beneath.
Any ideas for the two cases?
Thanks

Event Creation is not working

I have source "Source401" used for log "Log401". I need to use this source for "Log402" log and delete the log "Log401". (If we can rename “Log401” as “Log402” that is also fine. But all this need to be done programmatically)
With the code below, I am getting the following exception. What is the best way to achieve it?
Source Source401 already exists on the local computer.
Note: When I delete the old log, it is working fine. But the events are not getting created.
UPDATE
From MSDN
The operating system stores event logs as files. When you use EventLogInstaller or CreateEventSource to create a new event log, the associated file is stored in the %SystemRoot%\System32\Config directory on the specified computer. The file name is set by appending the first 8 characters of the Log property with the ".evt" file name extension.
The source must be unique on the local computer; a new source name cannot match an existing source name or an existing event log name. Each source can write to only one event log at a time; however, your application can use multiple sources to write to multiple event logs.
CODE
string source = "Source401";
string logName = "Log402";
string oldLogName = "Log401";
string eventName = "Sample Event";
string machineName = ".";
if (!EventLog.Exists(logName, machineName))
{
////Delete old log
//if (EventLog.Exists(oldLogName, machineName))
//{
// EventLog.Delete(oldLogName, machineName);
//}
//Create Source for the Log
EventLog.CreateEventSource(source, logName, machineName);
//Create Event
EventLog eventLog = new EventLog(logName, machineName, source);
eventLog.WriteEntry(eventName);
try
{
eventLog.WriteEntry(eventName, EventLogEntryType.Warning, 234, (short)3);
}
catch (Exception exception)
{
int x = 0;
}
The exception is telling you exactly what the problem is. The event source named "Source401" already exists. You're deleting the old event log, "Log401", but you're not deleting the event source.
As the documentation says:
The operating system stores event logs as files. When you use EventLogInstaller or CreateEventSource to create a new event log, the associated file is stored in the %SystemRoot%\System32\Config directory on the specified computer. The file name is set by appending the first 8 characters of the Log property with the ".evt" file name extension.
The source must be unique on the local computer; a new source name cannot match an existing source name or an existing event log name. Each source can write to only one event log at a time;
Also, this little nugget:
If a source has already been mapped to a log and you remap it to a new log, you must restart the computer for the changes to take effect.
In addition, you might want to consider this, also from the documentation:
Create the new event source during the installation of your application. This allows time for the operating system to refresh its list of registered event sources and their configuration. If the operating system has not refreshed its list of event sources, and you attempt to write an event with the new source, the write operation will fail
Finally, the CreateEventSource method you're calling is marked obsolete, and has been since .NET 2.0. There's usually a good reason for methods to be marked obsolete. You should be calling CreateEventSource(EventSourceCreationData).
I think you need to re-think the way you're using event logs. Your application shouldn't be creating and deleting logs that way. It's not how they're intended to be used.

Reading the Windows Event Log with C# (Source != ProviderName != SourceName)

I am using C# to read the Windows Event Log and I want to select/filter entries from it. The problem is that the information displayed in the Event Viewer is not always matching the data I get from c#.
for example:
EventViewer "Source": "User Profile Service"
Using the EventLogEntry class: Property "Source": "Microsoft-Windows-User Profiles Service"
Using the EventLogReader class: Property "ProviderName": "Microsoft-Windows-User Profiles Service"
Using WMI: "SourceName": "Microsoft-Windows-User Profiles Service"
I need to be able to read the exact information displayed in the EventViewer, where can I get this information from?
Reading the EventLog message...
When reading the EventLog message using the EventLogEntry class I occasionally get the following string:
The description for Event ID "xxx" in Source "xxx" cannot be found
Again, this does not match the message displayed in the EventViewer... I have tried using the EventLogReader.FormatDescription() method and it gives me the right (the same as the EventViewer) message, BUT for some entries it simply returns null, while the EventLogEntry.Message contains the proper text.
What is the correct way to retrieve the message of the event to get the same message as the one displayed in the EventViewer?
var eventLog = new EventLog("logName", "machine", "source");
foreach(var entry in eventLog.Entries)
{
}
That is a fairly basic swag at interacting with the log. If you need deeper filtering that source, you can write a LINQ query on the Entries. As shown here.
As for the error, one common reason is not having the proper access to the events and/or registry on the box in question. Since you can see data in question in EventViewer, I am suspecting a permissions error is a good possibility.
It appears that the "Source" string shown in the "Source" column in the Event Viewer is abbreviated. Also it seems that when you try to create an EventLog in C# only the logtype matters e.g. "Application", "System" etc. Once you create an EventLog it will contain all the entries for that logtype regardless of what you specified a source.
In order to get an event based on "Source" you want to iterate over the entries and filter only the entries for that "Source". Just keep in mind that the actual source name is not the same as what you see in the Event Viewer. For example for Source "Winlogon" the actual source name would be: "Microsoft-Windows-Winlogon" and so on.

Checking Event Log writing Permissions without writing an entry

I need to check if a user has write permissions for the event log. My solution right now is to write a test message in the log and delete it afterwards (so that the log does not get messed up, as the check for permissions is called often (every 3-5 Mins.) by some 'Healthcheck'-service:
const string log = "MyApplicationLog";
const string source = "PermissionCheck";
EventLog evLog;
try
{
if (!EventLog.SourceExists(source))
{
EventLog.CreateEventSource(source, log);
}
evLog = new EventLog();
evLog.Source = source;
evLog.WriteEntry("PermissionCheck Test Message");
return true;
}
finally
{
//remove the check messages:
if (EventLog.Exists(log))
{
EventLog.Delete(log);
}
}
Is there any possibility to check the permissions without actually writing a log entry?
Thank you in advance,
ElKunzo
Yes, AFAIK, using CAS. Decorate the required member/s with the EventLogPermission attribute, from there you can control whether you must have access, only desired and so forth.
This may well entail a little further adventure in CAS itself, however, if you're unfamiliar.
MSDN Link.

Categories

Resources