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.
Related
I wrote an application that use grpc with ASP.NET client/server.
This application is built for watch and inform about some operations.
Because I would to have an application also compatible with linux, I transformed it in a dll, then for Windows I made a little exe that uses it, with an icon in the systray.
It works for Windows, I must test for linux except for a part, I would to get the addresses used by the server after launching... it works if I back the dll in console mode, but with the short "launcher" it's impossible (add by edit) to get the addresses with the code i wrote between balises, BUT you can connect to the server (by example i changed port in config file to verify if it was not an address by default and it works.). My problem is only to retrieve addresses after launch, i need them to add the possibility to receive a mail with addresses to connect, show them in systray..
Yesterday I found this way to get addresses used:
public void Configure(IApplicationBuilder app,...)
{
string ServerAddress = app.ServerFeatures.Get<IServerAddressesFeature().Addresses.FirstOrDefault();
// ---
}
with the short launcher the string is null while it works when I back transform the dll as a program and launch it.
I would to have an easy way, without to make big modifications when I make an app for a system or another, I have chosen what was the more compatible and would to stay in this way if possible. I know i could make an identifier to know on which system I then launch according to the OS, but i hoped to find another way in case I want to make something else with this app.
Edit:
It seems it could be a problem between the fact to launch a systray that launch Kestrel. I'm beginner with Asp .net. I copy/paste contract and constructor to the systray, it seems i have the same problem (i used a different port). I can connect but IApplicationBuilder don't have the list of adresses used.
I upgrade my app which worked fine on Windows Server 2008(32 bit) from framework 3.5 to 4.5 for Windows Server 2012(64 bit). In the app, there is third party component runs on 32 bit. We cannot upgrade it because the supplier has no plans to update it. Therefore my app platform target is set for any CPU but Prefer 32-bit on my project property. All function is work except writing the event log. Would anyone provide suggestion to deal with this issue? Thank in advance.
There is my code to write the event log.
private static void RecordEventLog(string sMessage, EventLogEntryType ErrorType)
{
string source = "Testing App";
string logName = "Application";
string machineName = ".";
if (!EventLog.SourceExists(source, machineName))
{
EventSourceCreationData sourceData = new EventSourceCreationData(source, logName);
sourceData.MachineName = machineName;
EventLog.CreateEventSource(sourceData);
}
new EventLog(logName, machineName, source).WriteEntry(sMessage, ErrorType);
}
The problem may be the rights to create the event source - I can't see why 32 vs 64-bit would make a difference. You may have to run the app with admin privileges (at least the first time) to create the event source.
From MSDN:
To create an event source in Windows Vista and later or Windows Server
2003, you must have administrative privileges.
The reason for this requirement is that all event logs, including
security, must be searched to determine whether the event source is
unique. Starting with Windows Vista, users do not have permission to
access the security log; therefore, a SecurityException is thrown.
In Windows Vista and later, User Account Control (UAC) determines the
privileges of a user. If you are a member of the Built-in
Administrators group, you are assigned two run-time access tokens: a
standard user access token and an administrator access token. By
default, you are in the standard user role. To execute the code that
accesses the security log, you must first elevate your privileges from
standard user to administrator. You can do this when you start an
application by right-clicking the application icon and indicating that
you want to run as an administrator.
We have a Windows Service that checks a configuration file, and based on those settings, starts a new Process (let's call this ClusterProcess) which connects to a database and does the actual functionality.
There is a test project, that cuts out the Windows Service's part in the play, and just provides ClusterProcess with the necessary settings.
For our current test environment, we have the database on a cloud and I would say, rather restricted permissions.
My problem is this: when I run the test project, ClusterProcess gets its settings and things happen on the database. However, when I run the Windows Service, nothing gets changed on the database.
I've been using log4net to try and see where things fall over, but it seems to fail silently.
So the Windows Service calls this:
_ClusterRunnner.StartAllClusters();
In this method mentioned above, this is (amongst other things) what happens, and I get both log statements:
_ClusterProcesses = new List<Process>();
log.Debug("Cluster Name: " + cluster.Name + " ConfigPath: " + _ConfigPath);
_ClusterProcesses.Add(Process.Start(startInfo));
log.Debug("After process spawn.");
Okay, so the Process that it should start is ClusterProcess.exe, and in the Main method of that project I don't get any of the log statements that should be given, for instance:
log.Debug("Going to Start Processing");
_ClusterProcessor = new ClusterProcessor(config);
_ClusterProcessor.StartProcessing();
log.Debug("Finished Processing");
With log4net I have a special logger for ClusterProcess.exe (two appenders, a RollingFileAppender and an AdoNetAppender) and similar appenders for the Windows Service. (The Windows Service process holds a lock to its RollingFileAppender, so I had to create a special one for ClusterProcess.exe. The AdoNetAppenders are for nicely formatted logs after the connection to the database has been made.)
But now, the test project just calls this directly:
ClusterProcessor x = new ClusterProcessor(config);
x.StartProcessing();
and it works! I get the log statements in StartProcessing() and the database is changed.
So any ideas?
From my experience with services they run with very limited rights.
So if your Test(possible windows application) runs perfectly then I guess it has something to do with user rights.
I guess you can't realy access the filesystem so if your logger writes to a place on the harddrive you should think about the windows event log --> Write to Windows Application Event Log without registering an Event Source
To try if it has something to do with user rights just open your service in the windows service settings and let it log on as your administrator account and see if it has something to do with this.
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
Can someone tell me what the InteractiveProcessRunner is for? Is it identical to Process.Start?
Here is the class.
And here an example :
InteractiveProcessRunner runner =
new InteractiveProcessRunner(notepad.exe,hSessionToken);
THX
Whit this class you can run a process with the complete environment of the user active: if you call this code from a service, you should find the user mapped resources, the desktop and all the resources that are available when the user is loggen on interactively even if launched from a service ie not logged interactively.
The source code to which your link leads referes to this article: http://asprosys.blogspot.com/2009/03/perils-and-pitfalls-of-launching.html which explains the motivation behind it.
Summary: You can't really use Process.Start() when you want to start a new process as certain user from a windows service. The InteractiveProcessRunner lets you do this (supposedly, never used it so I can't verify it). So it's not the same as Process.Start() - it uses a different Windows API.