I am using Wix and installing an event log like:
<util:EventSource Log='MyLogName' Name='MyLogSource' EventMessageFile='%systemroot%\Microsoft.NET\Framework64\v4.0.30319\EventLogMessages.dll' />
I have a service that runs and tries to log to MyLogSource after installation. It does not begin to log unless I restart my system.
However, if I create the log in C# code, I can immediately log. The C# code can be in my service OnStart()
EventLog.CreateEventSource("MyLogSouce", "MyLogName");
I have a Systems.Diagnostics.EventLog instance named eventLog in my service class that is initialized like:
eventLog .Source = "MyLogSource"; // instance variable created in InitializeComponent()
To clarify, if I use Wix to create the event source (and therefore don't use the C# code to create it), then when the service starts and starts logging, nothing goes in the log. I have to reboot and then everything works.
However, if I comment out the Wix part to create the event source and do it in C# code, then when I start logging, the data goes in the log and no restart is necessary. My service does not really depend on any other services.
Is there some kind of trick to get it to work immediately if I install using Wix? Is there some way to use a <ServiceControl /> entry for my component so that I can restart or stop and start a service so that logging works without rebooting?
Update: 28 Oct 2021
I did go digging through the EventLog source code. It does not restart any services. However, it creates two event sources when creating an event source. When creating an Event source from WiX, it just creates the one event source.
So in Wix if I'm creating MyLogSource and MyLogName, it creates just the registry entries for those items.However, in the C# source code when calling the EventLog.CreateEventSource API, with the same arguments, it does create those items, however, it also creates another event source named MyEventLog.
So, in the registry tree, there is the event log MyEventLog, but under the key are the two event sources MyEventSource and MyEventLog.
Related
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.
I created an event log creator and it works perfect locally. When trying to create an event log remotely it gives me this message:
If the event originated on another computer, the display information
had to be saved with the event.
And it adds it to the event log.
My current method involves making registry changes on the remote servers. I read online that you can perform an event log remotely using a web service? I am completely lost in creating a web service as I have never made one before, can someone point me in the right direction. I'm also trying to avoid making registry changes on remote servers because they are in a production environment.
My current code:
else if (RemoteText.Text != "")
{
int EventID = Convert.ToInt32(EventIdText.Text);
string myLogName = "";
if (!EventLog.SourceExists(SourceText.Text))
{
//Create source.
EventLog.CreateEventSource(SourceText.Text, myLogName, RemoteText.Text);
Console.WriteLine("Creating EventSource");
}
else
{
// Get the EventLog associated if the source exists.
myLogName = EventLog.LogNameFromSourceName(SourceText.Text, RemoteText.Text);
EventLog myEventLog1 = new EventLog(myLogName, RemoteText.Text);
myEventLog1.Source = myLogName;
// Write an entry into log.
myEventLog1.WriteEntry("This is for your information",
EventLogEntryType.Error, EventID);
}
MessageBox.Show("Event Creation was SUCCESSFUL");
My goal is to remove the generic message on remote computer and avoid making registry changes on remote computer.
Creating an event source does indeed need write access priviliege on the HKLM\System\CurrentControlSet\eventlog key.
Try EventSourceCreationData, you may be missing the message file.
If you have administrator access on the remote machine and that said servers do not have remote registry turned off, you could use WMI to make registry permission changes and try your approach again.
If the event originated on another computer, the display information had to be saved with the event
You get this error if the event source is undefined. When you write an event log entry to the event log you basically only write an ID and some parameters associated with the event log entry. When you then view the event log entry Windows will use the message file associated with the event source to actually format the entry. From the ID a message template is retrieved and the parameters are replaced in the message template to create the formatted message that you can view in the event viewer. This approach makes it possible to provide translated event log messages for different language versions of Windows.
If the event source is undefined Windows cannot locate the message file and when you try to view the event log entry in the event viewer you get the error that you describe.
So to correctly log an event log entry to a source on a computer you need to create the source and this requires administrative write access to the registry (it can be done using an elevated installer). So your current approach seems to be the correct one and not something you should try to avoid.
Often .NET developers do not have any experience working with event log message files. The basic API in .NET to write to the event log will register and use a generic message file that simply substitutes whatever string parameter you supplied into the formatted message. This makes is quite easy to write to the event log from .NET but it also makes it a bit confusing because you do not realize that there is an intermediate message file required for it to work.
I need my service to check for existence and structure of certain files during its startup and exit/fail/stop if some conditions aren't met.
I read this thread: What is the proper way for a Windows service to fail?
but it does not help.
I set the ServiceBase.ExitCode property non-zero and then call ServiceBase.Stop. But I get 5 event log entries. See below:
Starting service. (I log this event via code)
Config.xml file not found. (I log this ERROR event via code)
Service stopped successfully. (SCM logs this message)
Service started successfully. (SCM logs this message)
Service cannot be started. The handle is invalid (SCM logs this message)
As you see everything goes OK except for the last two entries. Why are they there? What can I do to properly shutdown the service during startup? Why doesn't SCM see the service as stopped/failed?
You don't provide enough code to really know, but I suspect you are trying to validate the service and stop it in either the constructor or the OnStart. The way I like to handle services is start my timer in the OnStart. In the first interval of the timer I can validate all the code, if its invalid close the Service. If its valid, reset the interval of the timer to how frequently I want it to run then set a bool that tells it not to check for validity of files again.
What is the return code you are using for your ExitCode? If it matches the corresponding windows ExitCode, then that is what will be recorded by SCM. I'm assuming you are returning a 6 for your ExitCode.
The other thing is if you can run on Default values do that, let Config.xml be missing and just record the problem in the EventLog. "Configuration file Missing"
If you really want it to just abort during OnStart, set your ExitCode and then Throw an Exception (InvalidArgumentException, InvalidOperationException) for example
This article also has some good advice. .NET: Which Exception to Throw When a Required Configuration Setting is Missing?
You are trying to start second instance of service (another service registered for the same .exe)
There are certain circumstances in our application where non-fatal errors occur and the application recovers.
An example of this failing to correctly identify some importable items when populating said items to a selection list. The errors won't crash the app but a user would be alerted that some of the items failed to load.
In this case, the error is logged to the Application event log as a warning. It's a non-fatal error that the app recovers from, but logging to the event log allows us to see the original error if need be.
Our problem is that the software needs to be able to be installed with a Power User account. Not being an admin account, we won't have the ability to create custom event sources for the application.
The aim is to write the errors instead to the "Application" event source (which already exists appears in the Application event log). Doing this, however, causes text similar to the following to also be included.
The description for Event ID 0 from source Application cannot be found. Either the component that raises this event is not installed on your local computer or the installation is corrupted. You can install or repair the component on the local computer.
This is because the EventID is 0 when we write it. This approach will get the job done, but is there a a better way? Is there a non-admin way to specify the EventID for the Application Event source to indicate that it came from our app?
The error you see as The description for Event ID 0 from source Application cannot be found. Either the component that raises this event is not installed on your local computer or the installation is corrupted. You can install or repair the component on the local computer. is the result of the Application source's registered event message file not having an entry for event id 0. The message you see is the result of getting the template for the message id from the event message file and formatting it with the event payload.
I would not recommend in general that you hijack a source you don't own. Whoever is consuming those events has specific expectations about what they mean and what information they carry.
Regarding Is there a non-admin way to specify the EventID for the Application Event source to indicate that it came from our app?, what do you expect that event id specification would mean? The source is what determines where the event came from.
EDIT:
You will get the error in event viewer regardless of whether you provide an event id other than 0, because that source does not have an event message file registered. And even if it did, you would either have to use event ids that have an entry in the message file (confusing the consumers of the events) or event ids that do not have an entry and still get the error.
You are able to pass the Application Event ID as a parameter: ( example : 234 )
EventLog.WriteEntry("Application", "your log message here", EventLogEntryType.Warning, 234);
Further reading into EventLog.WriteEntry Method
http://msdn.microsoft.com/en-us/library/xzwc042w.aspx
I would like to ask about Windows services.
My service code looks like following:
try
{
//...
}
catch
{
Environment.ExitCode = 1;
}
After I install my service I am using a scheduling system to run service at a specific time:
net start MyService
//or
sc start MyService
So my question is, how to get information if I had exception?
Is there any command to get this information? Now I am usually running my application, then after 10 mins. stopping service. I want to do intermediate scheduling task which will tell me if in the application error has occurred. I have tried all options of "sc"- but it gives only information about service.
Contraints:
I cannot log errors and exceptions into the event log or files
Prefer not to change my code
In the scheduling system I can use bat scripting (so this scipt is only place I can change something)
The standard way is to log errors and exceptions into the event log - either a specific one you create for your service, or simply using the service as a new source for the event log.
You can use WMI to then check the event log periodically for errors.
In the absence of being able to log to the event log, can you create your own "event log"? Using either a file or database table that the intermediate service polls periodically might serve your purpose.