Runtime: EventLog without desktop framework installed results in "message is not found" logs in EventViewer

Created on 26 Oct 2018  路  22Comments  路  Source: dotnet/runtime

Original issue: https://github.com/aspnet/Logging/issues/858

As far as I understood from reading EventLog implementation it relies on EventLogMessages.dll file that shipped with the desktop framework and doesn't ship as part of .net core resulting in the message resource is present but the message is not found in the string/message table message being prepended to all event logs in event viewer.

Additionally EventLog.CreateEventSource(string, string) would create event source pointing to EventLogMessages.dll inside shared directory (C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.1.0\EventLogMessages.dll) that doesn't exist.

arch-arm64 area-System.Diagnostics.Tracing

Most helpful comment

@danmosemsft @pakrym Can we get this issue re-opened? The original issue was not about how overly verbose the error is, but as @eightvans said, the fact that you even get it in the first place. If you configure event logging via the provided .AddEventLog() extension method, you would expect that to just work instead of misconfiguring the registry settings to point to a dll that doesn't exist.

The problem being that if in my Program.cs I write:

WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(builder =>
{
    builder.AddEventLog(new EventLogSettings
    {
        SourceName = "MySource",
        LogName = "Application"
    });
});

The program will then create a registry setting in:

Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application\MySource

With an EventMessageFile set to

C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.2.6\EventLogMessages.dll

Which doesn't exist, which causes the verbose wrapping messages in the event log.

(This is with the .Net Core Hosting bundle 2.2.6 installed on Windows 10. The folder exists but not the file)

The fix I'd like to see is either EventLogMessages.dll is included in .net core at the location, or the registry entry is configured to point to something else that does exist.

All 22 comments

cc @danmosemsft

Isn't desktop framework a required windows component @pakrym? What is the configuration?

@anipik we should have a better error and probably not repeated.

I think some Windows Server Core installations come without one, maybe some windows docker base images too.

@danmosemsft Currently the error message is
The description for Event ID {0} in Source {1} cannot be found. The local computer may not have the necessary registry information or message DLL files to display the message, or you may not have permission to access them. The following information is part of the event:

The way the code is structured is that we can supply multiple message dlls paths separeted by semicolon. i can add a check to verify the paths of these dlls and modify the error message for this case

I think the main all was to not prepend "the message resource is present but the message is not found in the string/message table" since other than that it all works?

@Anipik I believe you established this is beyond .NET's control.

So if this "is beyond .NET's control", how do I get rid of this message? At the time I opened the original issue several months ago, I actually supplied a message DLL and it still didn't fix the problem!

the message resource is present but the message is not found in the string/message table string is prepended by event viewer or by something else.
Because if you try to retrive the message using eventlog or the eventing assembly, the value of the message does not contains the mentioned string.

This string is also prepended in the cases if you are not properly writing the event log i.e without explicitly mentioning source and log name

@Anipik So you are saying that application event logging can be established without this prepended message? If so, great! Is there a specific code example that explicitly shows how to do this? I am explicitly configuring it with the log source and log name as per the documentation that was available when I originally opened this issue and I did go through the pains to create message assembly and configure the path to the assembly, but perhaps the article I based my code on was outdated or erroneous?

So you are saying that application event logging can be established without this prepended message

C# string sourceName = "Mysource234234"; string logName = "Application"; using (EventLog el = new EventLog(logName)) { el.Source = sourceName; //EventLog.CreateEventSource(sourceName, logName); el.WriteEntry("my message is this new message"); Console.WriteLine(el.Entries.Count); Console.WriteLine(el.Entries[el.Entries.Count - 1].Message); }

this prints "my message is this new message" if eventlogmessages.dll is present other wise it wiil print
"The description for Event ID {0} in Source {1} cannot be found. The local computer may not have the necessary registry information or message DLL files to display the message, or you may not have permission to access them. The following information is part of the event: my message is this new message"

you can parse the message from the second string as well

Thanks for the clarification @Anipik. I'm afraid this is not the same issue as the original that I opened. I am not using System.Diagnostics.EventLog. My original issue that I opened, aspnet.Logging#858, pertains to using ILoggerFactory.AddEventLog() + ILogger.LogInformation(). I think we're perhaps discussing apples and oranges?

@fulte004 i looked over your code. Asp.net is using System.Diagnostics.EventLog to write the messages in the application log.

The description for Event ID 0 from source MyAppName 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.

If the event originated on another computer, the display information had to be saved with the event.

The following information was included with the event:

MyAppName [from Configuration]
User: USERNAME
Request: /api/Controller/Method

the message resource is present but the message is not found in the string/message table

What i was saying was that the last the message resource is present but the message is not found in the string/message table is not getting written by the .net or asp.net in the actual logs.
I am quite certain that it is added by Windows Event Log viewer application.
You can verify this by reading the eventLog entry in the code itself rather than viewing through event viewer.

Btw, there is no other way to write the eventlogs in .net core.

Okay, I just came across this same issue. I think the part that is a bug is that when a new EventSource is created it references a file that does not exist. It shipped in previous desktop versions of .net but does not ship with core. When creating an EventSource the registry entry should, by default, point to a file that does exist.

@danmosemsft @pakrym Can we get this issue re-opened? The original issue was not about how overly verbose the error is, but as @eightvans said, the fact that you even get it in the first place. If you configure event logging via the provided .AddEventLog() extension method, you would expect that to just work instead of misconfiguring the registry settings to point to a dll that doesn't exist.

The problem being that if in my Program.cs I write:

WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(builder =>
{
    builder.AddEventLog(new EventLogSettings
    {
        SourceName = "MySource",
        LogName = "Application"
    });
});

The program will then create a registry setting in:

Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application\MySource

With an EventMessageFile set to

C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.2.6\EventLogMessages.dll

Which doesn't exist, which causes the verbose wrapping messages in the event log.

(This is with the .Net Core Hosting bundle 2.2.6 installed on Windows 10. The folder exists but not the file)

The fix I'd like to see is either EventLogMessages.dll is included in .net core at the location, or the registry entry is configured to point to something else that does exist.

Another vote for reopening. I'm in the process of porting our services to .NET Core (or making it possible to run them under .NET Core, at least) and this issue, while not a showstopper, is a blemish, and is definitely the "fault" of the framework -- it relies on an EventLogMessages.dll that exists in Framework, but not Core, yet it blithely registers the event log source as if it was there anyway.

A proper fix would not be completely trivial -- even adding a reference to a shared DLL from the shared directory is obviously the Wrong Thing to do if the application is supposed to be a self-contained deployment. Arguably System.Diagnostics.EventLog should add this DLL to the artifacts. Framework gets around the need for having to build a separate EventLogMessages per application by simply pre-registering all event IDs with default formatting. A fairly elegant hack, but it still needs the resource DLL to be available for Event Viewer (and other things reading the event log).

An effective if clumsy operational workaround while this is not yet there is to create a symlink for the nonexistent file to just use the one from Framework, which can be assumed to exist, e.g.:

mklink "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.2.6\EventLogMessages.dll" "C:\Windows\Microsoft.NET\Framework\v4.0.30319\EventLogMessages.dll"

But this is not the approach CoreFX itself can take.

One more vote for reopening this issue.

Creating a new event source using .NET Core, adds a registry entry that points to a file that does not exist -> C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.2.6\EventLogMessages.dll.

/cc @danmosemsft

@Anipik please evaluate given all the feedback above.

.Net Core 3.1.0 has this issue:

Creating a new event source using .NET Core, adds a registry entry that points to a file that does not exist ->C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.1.0EventLogMessages.dll

MessageResourceFile should be provided by the user while creating an EventSource.
As a fallback mechanism, .Net Framework started providing a messageResourceFile(EventlogMessages.dll).
This resource file contains all the possible event ids. (1 - 16000 of them). The resource dll is used to return the message string without any locale modification.

The good thing is that all the necessary info associated with event is already shown by the event viewer.
We can fix the reading of the event log from the .Net core apis and also not create a registry key to a file that doesnt exist.

If you guys can give us some scenario where there is some loss of info while reading event using eventviewer or where having that extra string at the end is hindering some diagnostics, then we can take up the issue to fix that as well.

One possible solution for event viewer problem will be to just use one event id for writing the default case.

@Anipik Could you give an example of how a developer can provide a MessageResourceFile in .Net Core? When adding event logging to the pipeline via Microsoft.Extensions.Logging.AddEventLog, you provide an EventLogSettings which only contains LogName / MachineName / SourceName.

The issue is quite a bit more intrusive than you might think, as the extra string is not at the end of the message but at the beginning. Most logging tools will give you a snippet of the logs when looking at an overview of logs in aggregate, if we don't specifically write something in to strip this message off, we will see "The description for Event ID x from source y..." as the summary which actually does hinder diagnostics in practice.

More generally I'd like a way to write an application which can be configured correctly and doesn't put unnecessary strings in the outputted logs. Working around the problem forever isn't appropriate, and adding correct registry entries outside of .Net Core doesn't seem appropriate either.

@Anipik

With your statement that
MessageResourceFile should be provided by the user while creating an EventSource.

You actually need the c++ compiler to do this. You need to create a message file, compile the message file into a C header file and resource, and finally compile that it into a DLL.
https://docs.microsoft.com/en-us/windows/win32/eventlog/message-files

It's a very heavy burden that doesn't make sense in a dotnet app.

We don't generally care or want the old windows style of formatting messages and arguments (which this message file format was built around), since we do that ourselves in dotnet. We just need a message file like the one that was provided in .net fx that mapped each possible event ID to a single string.

It's not OK to ship a production application, and have these 'broken' error messages appear in the event logs.

It's a relatively simple inclusion, that means we have correctly represented log messages that are easy to read and diagnose issues with. Expecting dotnet developers to dive into C++ just to get a correctly outputted event log message seems a bit excessive.

So options are either
1) Dotnet core includes the existing message resource files from the framework (they are native windows dlls, not dependent on dotnet fx), and all event logging scenarios work out of the box as expected.

2) Developers create, compile (being aware of platform architecture because anycpu is not a thing in c++), and distribute their own message resource file, just to ensure that their event log messages display correctly in dotnet core

Most logging tools will give you a snippet of the logs when looking at an overview of logs in aggregate, if we don't specifically write something in to strip this message off, we will see "The description for Event ID x from source y..." as the summary which actually does hinder diagnostics in practice.

Are the logging tools scraping the text from the Event Viewer window? The event log APIs do not return that message.

You actually need the c++ compiler to do this. You need to create a message file, compile the message file into a C header file and resource, and finally compile that it into a DLL.

If you have an events.res file from rc.exe, you can use csc -nowarn:CS2008 -target:library -win32res:events.res -out:events.dll and not need a C++ compiler.

Microsoft.Diagnostics.Tracing.EventRegister embeds mc.exe and rc.exe, but it is intended for manifest-based events; IIRC, those encode version numbers and other things in event identifiers, which then might not match what aspnet/Logging and other libraries write to System.Diagnostics.EventLog.

We don't generally care or want the old windows style of formatting messages and arguments (which this message file format was built around), since we do that ourselves in dotnet.

The old Windows style has the advantage that the language of the events can be chosen by the user viewing them, rather than the software reporting them. But perhaps that is less important nowadays.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

yahorsi picture yahorsi  路  3Comments

GitAntoinee picture GitAntoinee  路  3Comments

omariom picture omariom  路  3Comments

nalywa picture nalywa  路  3Comments

iCodeWebApps picture iCodeWebApps  路  3Comments