Modify EventLogs using C# - c#

I need to read an entry from Windows Event Logs using the EventLog API, modify it and over-write that log entry.
For e.g.: if I do something like this:
log.Entries[0].Message = "Custom Message";
Then I get an error saying
"Error1 Property or indexer 'System.Diagnostics.EventLogEntry.Message' cannot be assigned to -- it is read only"
Is there any other way to do this?
Thanks in advance,
Kiran

No, Event logs can not be modified. the ReadOnly control is because of this.
You can create new logs or clear current logged items, but you can not modify an existing logged item! this is a privacy control

Write a Windows Event Logentry with the static EventLog Class.
Examplecode :
EventLog.WriteEntry( "your message", EventLogEntryType.<<yourtype>>);
For further information please consult the documentation (http://msdn.microsoft.com/en-us/library/system.diagnostics.eventlog.aspx).

Related

Missing Properties in Active Directory's ResultPropertyCollection

I have a ResultPropertyCollection object called resultValues.
I can view info about an AD user (eg their name) using this code:
resultValues["name"][0].ToString()
If I look up a user in Outlook's address book, I can see all the same info that I can see in C# as well as a photo of the user.
If Outlook is able to display the user's photo, why is it that resultValues["jpegPhoto"][0].ToString() and resultValues["photo"][0].ToString() throw System.ArgumentOutOfRangeException?
Wouldn't Outlook use the jpegPhoto attribute to retrieve the photo?
I worked it out, I need to use this attribute:
resultValues["thumbnailPhoto"][0];
However, why can't I find this attribute in the schema on MSDN?
(Answer found here: http://social.msdn.microsoft.com/Forums/vstudio/en-US/fc45bfd3-8a85-46cc-a687-95b99291ae1a/get-the-user-thumbnail-picture-from-active-directory?forum=csharpgeneral)
It's picture attribute, the attribute has Ldap-Display-Name thumbnailPhoto.
Take a look here http://msdn.microsoft.com/en-us/library/windows/desktop/ms680034(v=vs.85).aspx

Checking event entries/writing to event log only once

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.

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.

Directory Permission Watcher in c#

I have created the program which is monitoring a directory (e.g. \\server\share\folderXYZ) for changed events (like created, deleted, renamed and permission changes). I also got the notification if anything changed but I can't get exact details what has changed.
For example I have changed the permission for above directory from folder properties (Properties -> Security -> Edit ->Add new user or group or change permission for user and groups). File system watcher give notification if something changed but I can't get other details like:
For which user permission has changed?
Who changed the user permissions?
If any new group has been added(need to get all users in the group if new group added)?
If any new user is added to group and who added and need to get added user details?
If any user or group is removed than removed group or user details?
If any permission is added or changed for user than what permission are added or changed?
If any permission are changed for group than what permission changed?
Example Scenarios:
Action: At 11am, the Admin added User A to Trainees (Existing group)
Expected Result:
Access to \\server\share\folderXYZ changed: User A now has Read access, given by Admin at 11am, because he is now member of Trainees, which has Read Access.
Hope question is clear. I have done lots of search and couldn't find the solution. Please let me know if any API or Service available or any alternatives available?
-Thanks
The way to get the information you want is to use Windows Security Auditing, esp. since you want to know who made a change, not just what the change was.
The following code (and settings), produce output like this:
11-07-2011 17:43:10: 'Fujitsu\Grynn' changed security descriptor on file 'C:\Users\Grynn\Documents\ExcelTools\test.txt' from
'D:AI(A;;0x1200a9;;;BU)(A;ID;FA;;;S-1-5-21-559386011-2179397067-1987725642-1000)(A;ID;FA;;;SY)(A;ID;FA;;;BA)'
to
'D:ARAI(A;ID;FA;;;S-1-5-21-559386011-2179397067-1987725642-1000)(A;ID;FA;;;SY)(A;ID;FA;;;BA)'
using 'C:\Windows\explorer.exe'
12-07-2011 17:55:10: 'Fujitsu\Grynn' changed security descriptor on file 'C:\Users\Grynn\Documents\ExcelTools\test.txt' from
'D:AI(A;ID;FA;;;S-1-5-21-559386011-2179397067-1987725642-1000)(A;ID;FA;;;SY)(A;ID;FA;;;BA)'
to
'D:ARAI(D;;FA;;;S-1-5-21-559386011-2179397067-1987725642-1001)(A;ID;FA;;;S-1-5-21-559386011-2179397067-1987725642-1000)(A;ID;FA;;;SY)(A;ID;FA;;;BA)'
using 'C:\Windows\explorer.exe'
Turning on Auditing has 2 steps:
1. Use gpedit.msc to turn on "Audit Object access"
2. Modify "Auditing" for the folder you want to watch
Now whenever a File System Change event occurs (or via polling) query the security event log.
Code to query 'Security' event log:
var props = new EventLogPropertySelector(new string[] {
"Event/System/TimeCreated/#SystemTime",
"Event/EventData/Data[#Name='SubjectDomainName']",
"Event/EventData/Data[#Name='SubjectUserName']",
"Event/EventData/Data[#Name='ObjectName']",
"Event/EventData/Data[#Name='OldSd']",
"Event/EventData/Data[#Name='NewSd']",
"Event/EventData/Data[#Name='ProcessName']" });
using (var session = new System.Diagnostics.Eventing.Reader.EventLogSession())
{
//4670 == Permissions on an object were changed
var q = new EventLogQuery("Security", PathType.LogName, "*[System[(EventID=4670)]]");
q.Session = session;
EventLogReader rdr = new EventLogReader(q);
for (EventRecord eventInstance = rdr.ReadEvent();
null != eventInstance; eventInstance = rdr.ReadEvent())
{
var elr = ((EventLogRecord)eventInstance);
Console.WriteLine(
"{0}: '{1}\\{2}' changed security descriptor on file '{3}' from \n'{4}' \nto \n'{5}' \nusing '{6}'\n----\n",
elr.GetPropertyValues(props).ToArray());
}
}
From what i know/been reading, FileSystemWatcher can only tell you the file that was affected along with the change type only.
One way to go is for you to maintain a cache of the file attributes you're interested in, an in the presence of an event notifying a change, you query the cache to get the changes made and update it as necessary.

How to write to a custom event log?

I'm trying to get my .Net Windows Service to right to a custom event log. I'm using EventLogInstaller to create the event log and source when the application is installed. I read here that it takes a while for Windows to register the source so they reccomend you restart the application before trying to write to the log.
As this is a Windows Service I didn't want to have to force a computer restart or get the user to manually start the service up, so I use this code to wait for the log to exist and then start the service automatically.
while (!(EventLog.Exists("ManageIT") || EventLog.SourceExists("ManageIT Client Service")))
{
Thread.Sleep(1000);
}
System.ServiceProcess.ServiceController controller = new System.ServiceProcess.ServiceController("ManageIT.Client.Service");
controller.Start();
My problem is that events from the service are still written to the Application Log and although I can see my custom log in the Registry Editor it does not show up in the Windows 7 Event Viewer.
Any help will be much appreciated.
By default when a service is installed, the source gets associated with the Application Log.
If we change this association at a later point, the system needs a restart.
We can however prevent the association of the service with the application log, by setting autolog property to false in the service class (class which inherits from servicebase) constructor.
http://msdn.microsoft.com/en-us/library/system.serviceprocess.servicebase.autolog.aspx
Try this snippet:
edit - caveat: if the user running the code does not have administrator rights, this will throw an exception. Since this is the case (and if the user will not have these rights) best practices should be to assume the log exists, and simply write to it. see: The source was not found, but some or all event logs could not be searched
if (!EventLog.SourceExists("MyApplicationEventLog"))
{
EventSourceCreationData eventSourceData = new EventSourceCreationData("MyApplicationEventLog", "MyApplicationEventLog");
EventLog.CreateEventSource(eventSourceData);
}
using (EventLog myLogger = new EventLog("MyApplicationEventLog", ".", "MyApplicationEventLog"))
{
myLogger.WriteEntry("Error message", EventLogEntryType.Error);
myLogger.WriteEntry("Info message", EventLogEntryType.Information);
}
It sounds like you are writing to the event log like this:
EventLog.WriteEntry("Source", "Message");
This will write to the application log.
If you use the code in simons post with the creation of myLogger, you can specify the name of the Log.
I did something like this:
var logName = EventLog.LogNameFromSourceName("MyApp", Environment.MachineName);
//delete the source if it associated with the wrong Log
if (!string.IsNullOrEmpty(logName) & logName != "MyLog")
{
EventLog.DeleteEventSource("MyApp", Environment.MachineName);
}
if (!EventLog.SourceExists("MyApp"))
{
EventLog.CreateEventSource("MyApp", "MyLog");
}

Categories

Resources