System.Security.SecurityException when writing to Event Log C# - c#

My application is in C#.NET and it is deployed on different machines. Users of my application have normal access rights ( no ADMIN rights). On a few system I am getting System.Security.SecurityException. It says "System.Security.SecurityException: The source was not found, but some or all event logs could not be searched. Inaccessible logs: Security"
I did a few workarounds :-
on one machine I launched my app with admin rights, It worked fine - No issue.
I added user group in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Security.
It worked fine.
I dont want to go to every machine and do above workarounds. I need any generic workaround that can be applied once in all machine.
Any help?
Writing down a few lines of code :-
Config file :-
<add key="E_Source" Value="ABC">
C# code
Public static readonly string E_Source = ConfigManager.GetString("E_Source");
EventLog.writeEntry(E_Source, logtext, logtype);
Thanks in advance

To find the Source you want to write, .NET enumerates through all event logs. If it doesn't exist, .NET will eventually try enumerating through the Security log, for which you don't even have read rights as normal user. Thus, you get a SecurityException.
So you have to make sure that the event log exists (which AFAIK you can't do without triggering the exception). Normally, you would do that as part of your setup/install. Then, when writing, catch the SecurityException and handle it as appropriate (ex. show an error message that you couldn't write to the log).

If you're writing to the EventLog programmatically, you will need to create an event source with elevated permissions, as noted in the documentation on the EventLog class:
https://msdn.microsoft.com/en-us/library/system.diagnostics.eventlog%28v=vs.110%29.aspx

Related

Way to copy parts of windowsEventLog to a defined location? (sec,app, sys)

I need to create three seperate evtx files containing all events from the last X days found in each eventLog (security, application, system) and save those files in a defined location.
I am using c# to implement the functionality. It is also possible to execute a powershell script / bat file. If administration rights are a problem is it possible to do this for application and system only?
From my understanding:
It is not possible to create eventLogs in custom locations without changing the registry.
It is not possible to create eventLogs in the default location without Administration Rights since for creating a new eventlog file it needs to make sure that the eventlog is not already existing and it is not possible to access the security eventLog to check.
Exception message:
"The source was not found, but some or all event logs could not be searched. To create the source, you need permission to read all event logs to make sure that the new source name is unique. Inaccessible logs: Security."
Creating a evtx file with File.Create Method (String) and writing to it with File.WriteAllText Method (String, String) is also not possible
I also tried doing all of this with a powershell script but I pretty much ran into the same problems. $foo = Get-EventLog System -after (Get-Date).addays(-3) -asbaseobject
Check out this VERY useful cmdlet--which I think should have natively shipped with Windows-- Export-EventLog by Jeffrey Patton on TechNet.
It gives you a new function you can run called Export-EventLog, which even allows you to specify a custom location! It even runs on remote computers!
Export-EventLogs -ComputerName $computerName -Credential (Get-Credential) -LogName Application -Destination 'C:\LogFiles1\Application.evtx'

System.Runtime.InteropServices.COMException (0x80080005): Retrieving the COM class factory for component with CLSID

I am replacing MS Word MergeFields with data from SQL Server in a simple asp.net c# application and it works fine locally but when i publish it often i get the following:
System.Runtime.InteropServices.COMException (0x80080005): Retrieving the COM class factory for component with CLSID {00020906-0000-0000-C000-000000000046} failed due to the following error: 80080005.
I tried giving both IIS_IUSRS and NETWORK SERVICE full access, and also set the identity to interactive in the DCOM config but it didn't fix anything.
For nasty permissions stopping you from doing what you expect, (I've encountered in the past too). Sometimes I've had to change my DCOM/COM+ permissions to an object too. At the DCOM Config tab screen for your project, under security, make sure BOTH "Launch and Activation" and "Access" have been customized to explicitly include the user account you intend to allow.
Now, one more thing -- just to rule out all others. I've even gone the extent (for testing / confirmation only) is that on the "Identity" tab, you can select the "Interactive User", "Launching User" or "This User". I would put in your actual account that you KNOW has permissions (ensure your account is also in the launch and activation... and access permissions on previous tab). And also to enter/confirm your password.
If that still fails, then I would try adding the ADMIN account for permissions and try that... just for purposes of yes, its permissions based on a user. Once confirmed, you can scale it back, and even create some simplified restricted user who's primary purpose is to run this utility, and this new user has its adequate permissions to do so.
Once that is done, you should be good to go.
Now, that said, I've run into another flakey thing and its been a while, so it may not be an issue any more. Periodically, during certain "Windows" updates, the functionality would just stop working. However, if all I did was go back into user maintenance, do change password for the account (even if just keeping it the same original password) and saving it, then going back into DCOM and enter/re-confirm saving it there too, all became functional again.
You should share the folder where you save the document that is created from the template with the NETWORK SERVICE user.
Change the dcomcnfg identity to interactive instead of launching user.
Reference: Error : 80070005, there is something in this forum about
Retrieving the COM class factory for component with CLSID {7979FAA5-3A2A-4E50-A2C9-286C6F34C1D3} failed due to the following error: 80080005

Windows service can't write to %LOCALAPPDATA%

I have built an app that works only when not run as a Windows service. Well, the service runs, but it doesn't do what it should. The service uses the Local Service account. So to kick off debugging, I thought I'd start with something simple: have it create a directory when it starts:
Directory.CreateDirectory(
Environment.SpecialFolder.LocalApplicationData + "\\MyService");
When I started the service, it stopped almost immediately and Windows reported that fact. When I commented out the above statement, recompiled and re-installed, the service ran without stopping.
Obviously the above line throws an exception of some sort. I have no way of logging the error because I can't write to the file system. Any ideas why Local Service can't create a directory in its own %LOCALAPPDATA%?
You should use GetFolderPath with LocalApplicationData like so:
string folderName = Path.Combine(Environment.GetFolderPath(
Environment.SpecialFolder.LocalApplicationData),
"MyService");
Directory.CreateDirectory(folderName)
I think this might be because there is no special folder. When running as the local service account you are running under that user, not the logged in user. so you are requesting a special folder that probably wont exist, as I don't think the local service has a profile. (I may be wrong) - I was wrong :p
Just in case anyone pops by:
C:\Windows\ServiceProfiles\LocalService
is the local service profile folder, so it will end up in there.
If you want to debug it surround that line with a try catch, and then write the error to a file:
try
{
Directory.CreateDirectory(Environment.SpecialFolder.LocalApplicationData + "\\MyService");
}
catch (Exception ex)
{
System.IO.StreamWriter file = new System.IO.StreamWriter(#"C:\MyServicelog.txt",true);
file.WriteLine(ex.Message);
file.Close();
}
At least then you can see whats causing the error
Martyn
I suggest you write the exception details to the event log. All user accounts have permission to write to the event log as long as the log and source names have already been created by an administrator (which you can do simply by running the app as yourself first).
As to the root cause of the error, it may be because LocalService doesn't normally get a full set of profile folders created by default. I'm not sure whether this is by design, or simply what I have observed on various machines.

Read Event Log Remotely with .NET

I want to read the Event Log on a remote computer to check for errors during testing. Here's some relevant code:
public bool CheckEventLogs(DateTime start)
{
EventLog myEventLog = new EventLog("CustomLog", "ServerName");
bool errorFound = false;
foreach (EventLogEntry entry in myEventLog.Entries)
{
if (entry.EntryType == EventLogEntryType.Error && entry.TimeGenerated >= start)
{
Console.WriteLine("Error in Event Log:\n" + entry.Message + "\n");
errorFound = true;
}
}
return errorFound;
}
Currently, this code throws an exception (Attempted to perform an unauthorized operation). According to MSDN, I need EventLogPermission, but I have been struggling to find any examples of how to use this permission. Does anyone have an example of how to do this?
Edit: Response to Comments
Thank you all for the comments - here is the additional information requested:
The exception is thrown from the foreach statement. Specifically, when stepping through the code it thrown in the step after when in is highlighted. It seems that I was able to create the event log object but I'm not able to access the entries in the event log.
My account does not have permission to read the event log on the target system, but I have credentials for an account which does. When connecting manually through the event viewer there is an option to connect as another user. After doing this manually, then my code ran without a problem. However, I cannot rely doing it manually every time this program runs. What I need is a way to connect as another user programmaticly. I thought that the EventLogPermission would be the way to do that, but maybe there is another way. If anyone knows how to connect to a remote log as a different user in C#, that would be exactly what I was looking for.
WMI is incredibly useful for this, a snippet like
SELECT Logfile,TimeGenerated,Type,SourceName,Message FROM Win32_NTLogEvent
Would allow you to query the logs. This utility from MS will allow you to explore WMI and will even build the .net code to invoke the queries.
Another benefit to this is that its going to get all the events and bring them local to the application where you can parse them at your leisure. Iterating the events in the way you are doing now is prone to failure if the connection is broken while you are processing (incidentally this is the same method that is typically employed with database access).
Thanks to everyone who provided comments on this question. Once I realized that the permissions might not be a part of .NET but part of Windows and the Event Viewer itself, I had some new direction for my own investigations.
It looks like a "net use" command was all that was needed to establish the connection between my local computer and the remote computer. When calling "net use" before using the code I posted in the question, things worked beautifully. It is simple enough to call that from the code before reading from the event log.
Thanks again for your help!

UAC gives me fits!

The code I am currently working on runs on Windows Server 2003, but needs to be able to write to EventLogs on multiple machines. I am coding in C#, using VS2008 Pro, and .NET Framework 3.5.
The code itself is relatively simple (thanks to the framework):
using (EventLog remoteEvtLog = new EventLog(LogName, HostName, EventSource))
{
remoteEvtLog.WriteEntry(Body);
}
"LogName" is a string containing the name of the log to write to - in most cases "Application".
"HostName" is a string containing the NetBIOS Name of the machine where the log entry should be written.
"EventSource" is a string containing the name of the event sender (this is a utility used by multiple apps, so usually it will have the name of the consuming application).
"Body" is a string containing the text to be written to the event log.
In most cases this works fine, but when the machine being written to uses UAC, any write which creates a new EventSource fails. This occurs even though the Security credentials used are members of the Administrators group - and I have not been able to find a way to specify the elevated priviledge level. Apparently, members of the Administrators goroup get two tokens - one limited, and one elevated, but as far as I can tell, the only way to specifiy the elevated token is through the UI - which is obviously a problem when remotely accessing the Logs.
Any ideas out there?
Your code is not supposed to create new event sources (the legacy auto-create behavior is unfortunate, but still wrong). If you need a separate event source for your application, then the installer for that application - which runs with elevated administrative privileges - should create it.

Categories

Resources