TypeInitializationException in NLog LoggerFactory - c#

I develop a WPF application that uses NLog. It has been deployed to a few prospective customers, and in one of them, the application worked fine for a week and now it doesn't even open. That is, you double click the app icon, and nothing happens, literally. Not even the logging inside a AppDomain.CurrentDomain.UnhandledException catch clause.
I was able to identify an event in the Windows Event Viewer (see message below).
What bogs me down is the sudden appearence of this error after a week of flawless operation, and my inability to interpret this message or finding info about it online.
Aplicativo: ForceViewer.exe
Versão do Framework: v4.0.30319
Descrição: O processo foi terminado devido a uma exceção sem tratamento.
Informações da Exceção: System.Xml.XmlException
em System.Xml.XmlTextReaderImpl.Throw(System.Exception)
em System.Xml.XmlTextReaderImpl.ParseDocumentContent()
em System.Xml.XmlTextReaderImpl.Read()
em System.Xml.XmlTextReader.Read()
em System.Configuration.XmlUtil..ctor(System.IO.Stream, System.String, Boolean, System.Configuration.ConfigurationSchemaErrors)
em System.Configuration.BaseConfigurationRecord.InitConfigFromFile()
Informações da Exceção: System.Configuration.ConfigurationErrorsException
em System.Configuration.ConfigurationSchemaErrors.ThrowIfErrors(Boolean)
em System.Configuration.BaseConfigurationRecord.ThrowIfParseErrors(System.Configuration.ConfigurationSchemaErrors)
em System.Configuration.BaseConfigurationRecord.ThrowIfInitErrors()
em System.Configuration.ClientConfigurationSystem.OnConfigRemoved(System.Object, System.Configuration.Internal.InternalConfigEventArgs)
Informações da Exceção: System.Configuration.ConfigurationErrorsException
em System.Configuration.ConfigurationManager.PrepareConfigSystem()
em System.Configuration.ConfigurationManager.get_AppSettings()
em NLog.Common.InternalLogger.GetSettingString(System.String, System.String)
em NLog.Common.InternalLogger.GetSetting[[System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]](System.String, System.String, Boolean)
em NLog.Common.InternalLogger.Reset()
em NLog.Common.InternalLogger..cctor()
Informações da Exceção: System.TypeInitializationException
em NLog.Common.InternalLogger.Log(System.Exception, NLog.LogLevel, System.String)
em NLog.Internal.ExceptionHelper.MustBeRethrown(System.Exception)
em NLog.LogFactory.get_Configuration()
em NLog.LogFactory.GetLogger(LoggerCacheKey)
em NLog.LogFactory.GetLogger(System.String)
em NLog.LogManager.GetLogger(System.String)
em Miotec.ForceViewer.App..cctor()
Informações da Exceção: System.TypeInitializationException
em Miotec.ForceViewer.App.Main(System.String[])
Here is my App.xaml.cs:
public partial class App : Application
{
static string AppName = "ForceViewer 1.1";
static readonly Mutex mutex = new Mutex(true, AppName);
// APPARENTLY the exception happens in the line below:
static readonly Logger logger = LogManager.GetLogger(typeof(App).FullName);
[STAThread]
public static void Main(string[] args)
{
SplashScreen splashScreen = new SplashScreen("Splash.png");
splashScreen.Show(true);
if (mutex.WaitOne(TimeSpan.Zero, true))
{
var app = new App();
app.InitializeComponent();
app.Run();
mutex.ReleaseMutex();
}
else
{
Extensions.EnviaMensagemPraAtivarOutraJanela();
}
}
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
WpfLauncher.Launch(this, new ForceViewerBootstrapper(AppName));
logger.Info($"Aplicação {AppName} iniciada");
}
}
UPDATE (with additional, possibly relevant info):
Some people mentioned NLog XML config file, but I am using a runtime configuration, as follows:
var dirname = Path.Combine(#"C:\\AppFolder", appName, "logs");
Directory.CreateDirectory(dirname);
var filename = Path.Combine(dirname, $"{appName}.log");
var filetarget = new FileTarget("app")
{
FileName = filename,
Encoding = Encoding.UTF8,
Layout = "${longdate}|${level:uppercase=true}|${message} (${logger:shortName=true})",
AutoFlush = true,
MaxArchiveFiles = 8,
ArchiveAboveSize = 1048576,
ArchiveEvery = FileArchivePeriod.Friday,
ConcurrentWrites = true
};
var asyncTarget = new AsyncTargetWrapper("app", filetarget);
var config = new LoggingConfiguration();
config.AddRuleForAllLevels(asyncTarget);
config.AddTarget(asyncTarget);
LogManager.Configuration = config;
Additionally, the "stack trace" (which in the case of a Windows Event seems to be printed sort of backwards) suggests NLog itself is getting an exception from the System.Configuration classes, as seen from decompilation of InternalLogger:
namespace NLog.Common
{
//...
public static class InternalLogger
{
//...
private static string GetSettingString(string configName, string envName)
{
// Line below seems to be throwing an exception
string str = System.Configuration.ConfigurationManager.AppSettings[configName];
//..

Probably there is a config mistake in your NLog (XML) config.
So why do you get a TypeInitializationException and not a helpful message? That's because your initializing NLog before starting your program. The line:
static readonly Logger logger = LogManager.GetLogger(typeof(App).FullName);
will be run before the Main because it's a static field. Unfortunately NLog cannot throw a better exception (see: Better TypeInitializationException (innerException is also null))
Recommendation: in this case is recommend to have a non-static Logger, or, a static Lazy<Logger>:
static readonly Lazy<Logger> logger = new Lazy<Logger>(() => LogManager.GetLogger(typeof(App).FullName));

Related

The type initializer for Test.Program threw an exception

In a .net5.0 project I'm trying to read all mails from txt file, it worked half an hour ago but suddenly when I changed some names for better understanding it stoped working.
I read the txt file location from app.config file and this is the config:
[![enter image description here][1]][1]
The key Im reading is LokacijaExportanihMailAdresa.
This is the key in app.config;
<add key="LokacijaExportanihMailAdresa" value="txt_docs\Mailovi.txt"
This is the code with which im trying to read the txt file:
class Program
{
public static int i = 0;
public static Timer aTimer = new Timer(Int32.Parse(ConfigurationManager.AppSettings.Get("VrijemeUMiliSekundama")));
public static string lokacijaMailova = ConfigurationManager.AppSettings.Get("LokacijaExportanihMailAdresa");
public static string posiljatelj = ConfigurationManager.AppSettings.Get("Posiljatelj");
public static string subjekt = ConfigurationManager.AppSettings.Get("Predmet");
public static string putanjaDoPoruke = ConfigurationManager.AppSettings.Get("Poruka");
public static int imaPrivitak = Int32.Parse(ConfigurationManager.AppSettings.Get("ImaAttachment"));
public static string putanjaDoPrivitka = ConfigurationManager.AppSettings.Get("Privitak");
public static string smtpServer = ConfigurationManager.AppSettings.Get("SmtpServer");
static void Main(string[] args)
{
var logger = NLog.LogManager.GetCurrentClassLogger();
logger.Info("Aplikacija je pokrenuta");
var mailovi = File.ReadAllLines(lokacijaMailova);
aTimer.Elapsed += (sender, e) => OnTimedEvent(sender, e, logger, mailovi, i++);
aTimer.Start();
Console.ReadKey();
}
}
This is the Error:
2021-11-09 13:23:01.6441|Error|MailServis.Program|System.TypeInitializationException: The type initializer for 'MailServis.Program' threw an exception.
---> System.ArgumentNullException: Value cannot be null. (Parameter 's')
at System.Int32.Parse(String s)
at MailServis.Program..cctor() in C:\Users\djcumbaj\source\repos\MailServis\Program.cs:line 21
--- End of inner exception stack trace ---
at MailServis.Program.Main(String[] args) in C:\Users\djcumbaj\source\repos\MailServis\Program.cs:line 32 |
But after I put the path directly in File.ReadAllLines it reads the file but the next thing that happens the Timer throws the same exception when i mean the same it's exactly the same.
Thank you in advance.
You call ConfigurationManager.AppSettings.Get("ImaAttachment") but you have ImaPrivitak in the appSettings.

Mono.Cecil AssemblyDefinition.ReadAssembly(): No symbol found for file

I am using Mono.Cecil 0.10.3.0, the latest version from nuget.
This line:
var ad = AssemblyDefinition.ReadAssembly(#"C:\path\to\my\library.dll", new ReaderParameters { ReadSymbols = true });
throws exception:
Mono.Cecil.Cil.SymbolsNotFoundException was unhandled by user code
HResult=-2147024894
Message=No symbol found for file: C:\path\to\my\library.dll
Source=Mono.Cecil
StackTrace:
at Mono.Cecil.Cil.DefaultSymbolReaderProvider.GetSymbolReader(ModuleDefinition module, String fileName)
at Mono.Cecil.ModuleReader.ReadSymbols(ModuleDefinition module, ReaderParameters parameters)
at Mono.Cecil.ModuleReader.CreateModule(Image image, ReaderParameters parameters)
at Mono.Cecil.ModuleDefinition.ReadModule(String fileName, ReaderParameters parameters)
at Mono.Cecil.AssemblyDefinition.ReadAssembly(String fileName, ReaderParameters parameters)
What does this error mean? Is it not finding library.pdb? Because the .pdb file exists.
Here's another strange this about this issue. The ReadAssembly() call will work fine in one version of the code set, but then I will create a new branch of code in git, and try the same line in the new branch, and it will fail.
I am not sure this will help you, and I have never used this personally, but I looked through the code here and commented it for your amusement.
static void ReadSymbols(ModuleDefinition module, ReaderParameters parameters)
{
var symbol_reader_provider = parameters.SymbolReaderProvider;
if (symbol_reader_provider == null && parameters.ReadSymbols)
symbol_reader_provider = new DefaultSymbolReaderProvider(); // we get here
if (symbol_reader_provider != null)
{
module.SymbolReaderProvider = symbol_reader_provider;
var reader = parameters.SymbolStream != null
? symbol_reader_provider.GetSymbolReader(module, parameters.SymbolStream)
: symbol_reader_provider.GetSymbolReader(module, module.FileName); // we get here
...
}
...
}
Implementation of GetSymbolReader
public ISymbolReader GetSymbolReader(ModuleDefinition module, string fileName)
{
...
// this just changes the extension
var pdb_file_name = Mixin.GetPdbFileName(fileName);
// this should be true
if (File.Exists(pdb_file_name))
{
if (Mixin.IsPortablePdb(Mixin.GetPdbFileName(fileName)))
return new PortablePdbReaderProvider().GetSymbolReader(module, fileName);
try
{
return SymbolProvider.GetReaderProvider(SymbolKind.NativePdb).GetSymbolReader(module, fileName);
}
catch (Exception)
{
// We might not include support for native pdbs.
}
}
// can't find the pdb file, your error
if (throw_if_no_symbol)
throw new SymbolsNotFoundException(string.Format("No symbol found for file: {0}", fileName));
return null;
}
Definition of GetPdbFileName
public static string GetPdbFileName(string assemblyFileName)
{
return Path.ChangeExtension(assemblyFileName, ".pdb");
}
So as you can see, something is amiss here. All this code does is
Change the extension of your file name to look for the PBD,
Checks if it the PBD file exists,
If not, throws the exception you are getting
I think you need to double check everything, also note, the
// We might not include support for native pdbs.
It's the only other way this error can throw.

Add a firewall rule for Distributed Transaction Coordinator (msdtc.exe)

I tried to use firewallAPI.dll to add a rule. It works fine for calc.exe (or some other files) as described bellow but fails for msdtc.exe with the following exception:
System.IO.FileNotFoundException: 'The system cannot find the file
specified. (Exception from HRESULT: 0x80070002)'
Example:
static void Main(string[] args)
{
var manager = GetFirewallManager();
if (manager.LocalPolicy.CurrentProfile.FirewallEnabled)
{
var path = #"C:\Windows\System32\calc.exe";
//var path = #"C:\Windows\System32\msdtc.exe"; // System.IO.FileNotFoundException: 'The system cannot find the file specified.
AuthorizeApplication("Test", path, NET_FW_SCOPE_.NET_FW_SCOPE_ALL, NET_FW_IP_VERSION_.NET_FW_IP_VERSION_ANY);
}
}
private const string CLSID_FIREWALL_MANAGER =
"{304CE942-6E39-40D8-943A-B913C40C9CD4}";
private static NetFwTypeLib.INetFwMgr GetFirewallManager()
{
Type objectType = Type.GetTypeFromCLSID(
new Guid(CLSID_FIREWALL_MANAGER));
return Activator.CreateInstance(objectType)
as NetFwTypeLib.INetFwMgr;
}
private const string PROGID_AUTHORIZED_APPLICATION =
"HNetCfg.FwAuthorizedApplication";
public static bool AuthorizeApplication(string title, string applicationPath,
NET_FW_SCOPE_ scope, NET_FW_IP_VERSION_ ipVersion)
{
// Create the type from prog id
Type type = Type.GetTypeFromProgID(PROGID_AUTHORIZED_APPLICATION);
INetFwAuthorizedApplication auth = Activator.CreateInstance(type)
as INetFwAuthorizedApplication;
auth.Name = title;
auth.ProcessImageFileName = applicationPath;
auth.Scope = scope;
auth.IpVersion = ipVersion;
auth.Enabled = true;
INetFwMgr manager = GetFirewallManager();
manager.LocalPolicy.CurrentProfile.AuthorizedApplications.Add(auth);
return true;
}
Note: I checked the folder and see the file is located properly...
Could anybody help to add firewall rule for Distributed Transaction Coordinator? Maybe I should try to add another file to firewall (not msdtc.exe)?
Project > Properties > Build tab, untick the "Prefer 32-bit" checkbox. You don't prefer it, there is no 32-bit version of msdtc.exe.
Why the file system redirector caused the FileNotFoundException is explained well in this MSDN article.

NLog Exception on Log to File (Unity project)

I'm using programmatic configuration with NLog and am encountering the following error whenever the log file should be written to:
ArgumentOutOfRangeException: Argument is out of range.
System.Security.AccessControl.AuthorizationRule..ctor
(System.Security.Principal.IdentityReference identity, Int32
accessMask, Boolean isInherited, InheritanceFlags inheritanceFlags,
PropagationFlags propagationFlags) (at
/Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Security.AccessControl/AuthorizationRule.cs:61)
System.Security.AccessControl.AccessRule..ctor
(System.Security.Principal.IdentityReference identity, Int32
accessMask, Boolean isInherited, InheritanceFlags inheritanceFlags,
PropagationFlags propagationFlags, AccessControlType type)
System.Security.AccessControl.MutexAccessRule..ctor
(System.Security.Principal.IdentityReference identity, MutexRights
eventRights, AccessControlType type)
NLog.Internal.FileAppenders.BaseFileAppender.CreateSharableMutex
(System.String mutexNamePrefix)
NLog.Internal.FileAppenders.BaseFileAppender.CreateSharableArchiveMutex
()
NLog.Internal.FileAppenders.RetryingMultiProcessFileAppender.CreateArchiveMutex
() NLog.Internal.FileAppenders.BaseFileAppender..ctor (System.String
fileName, ICreateFileParameters createParameters)
NLog.Internal.FileAppenders.RetryingMultiProcessFileAppender..ctor
(System.String fileName, ICreateFileParameters parameters)
NLog.Internal.FileAppenders.RetryingMultiProcessFileAppender+Factory.NLog.Internal.FileAppenders.IFileAppenderFactory.Open
(System.String fileName, ICreateFileParameters parameters)
NLog.Internal.FileAppenders.FileAppenderCache.AllocateAppender
(System.String fileName) NLog.Targets.FileTarget.WriteToFile
(System.String fileName, NLog.LogEventInfo logEvent, System.Byte[]
bytes, Boolean justData) NLog.Targets.FileTarget.ProcessLogEvent
(NLog.LogEventInfo logEvent, System.String fileName, System.Byte[]
bytesToWrite) NLog.Targets.FileTarget.Write (NLog.LogEventInfo
logEvent) NLog.Targets.Target.Write (AsyncLogEventInfo logEvent)
Google doesn't know anything about this error, as far as I can see. The following is my configuration code:
public static void SetupLogging()
{
// Can unity debug be redirected to go through Nlog?
var config = new LoggingConfiguration();
var consoleTarget = new ConsoleTarget("console");
config.AddTarget("console", consoleTarget);
//var logsPath = UtilsIO.GetResourcesPath(UtilsIO.ResourceType.Logs, "_logs");
var logsPath = #"d:\jem\temp\_logs";
var dir = logsPath + "\\app" + "\\" + Environment.UserName;
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
var filepath = Path.Combine(dir, Guid.NewGuid() + ".log");
var fileTarget = new FileTarget("file")
{
FileName = filepath,
Layout = "${date:format=yyyyMMddHHmmss} ${message}"
};
config.AddTarget("file", fileTarget);
var rule1 = new LoggingRule("*", LogLevel.Debug, consoleTarget);
config.LoggingRules.Add(rule1);
var rule2 = new LoggingRule("*", LogLevel.Debug, fileTarget);
config.LoggingRules.Add(rule2);
InternalLogger.LogToConsole = true;
LogManager.ThrowExceptions = true;
LogManager.Configuration = config;
}
This is how I instantiate the logger:
private static NLog.Logger logger = LogManager.GetLogger("file");
And this is how I use that instantiation:
logger.Debug("Hello world????");
I've tried using the ImpersonatingTargetWrapper but get the same error. I've given 'Everyone' full rights to the root directory. I've also tried configuration file to get started, but that didn't help either. I've banged my head for a while against this one - anyone have any suggestions?
NLog 4.4.1 now performs runtime detection of MONO version, and avoids using named mutex if not running MONO ver. 4 or newer (Unity is running MONO ver. 2)

Enterprise Library 5.0: Writing log to file without XML configuration

There is some code for logging to file. I dont using app.config
class Program
{
static void Main(string[] args)
{
MyLogger.Write("This is message error", "My Category");
Console.ReadKey();
}
}
public static class MyLogger
{
static readonly LogWriterImpl _writer;
static MyLogger()
{
TextFormatter formatter = new TextFormatter
("Timestamp: {timestamp}{newline}" +
"Message: {message}{newline}" +
"Category: {category}{newline}");
var logFileListener = new Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener
(
"c:\\messages.log", "----------", "----------", formatter
);
LogSource mainLogSource = new LogSource("MainLogSource", SourceLevels.All);
mainLogSource.Listeners.Add(logFileListener);
LogSource nonExistantLogSource = new LogSource("Empty");
IDictionary<string, LogSource> traceSources = new Dictionary<string, LogSource>();
traceSources.Add("Error", mainLogSource);
traceSources.Add("Debug", mainLogSource);
_writer = new LogWriterImpl
(
new Microsoft.Practices.EnterpriseLibrary.Logging.Filters.ILogFilter[0],
traceSources,
nonExistantLogSource,
nonExistantLogSource,
mainLogSource,
"Error",
false,
true
);
}
public static void Write(string message)
{
Write(message, "Error");
}
public static void Write(string message, string category)
{
LogEntry entry = new LogEntry();
entry.Categories.Add(category);
entry.Message = message;
_writer.Write(entry);
}
}
This program work without errors but it don't create log file c:\messages.log and don't write log entity. Where is the error? I don't want using application config file in my project
There could be a couple of reasons (at least!) why you are not seeing any logging:
The categories that are configured for logging are "Error" and "Debug" but when you call MyLogger.Write you are passing a category of "My Category"
There could be a permission problem. Writing to the root of the drive is frequently restricted
As an aside, you should probably store the reference to LogWriterImpl as the base class LogWriter.
As another aside, instead of using the logging classes directly it is preferable to use the Fluent Configuration API which was released as part of version 5.0. It makes this type of configuration much simpler. As an example:
var builder = new ConfigurationSourceBuilder();
builder.ConfigureLogging()
.WithOptions
.DoNotRevertImpersonation()
.LogToCategoryNamed("My Category")
.SendTo.FlatFile("MyMessages")
.FormatWith(new FormatterBuilder()
.TextFormatterNamed("Text Formatter")
.UsingTemplate("Timestamp: {timestamp}...{newline})}"))
.ToFile("c:\\messages.log");
var configSource = new DictionaryConfigurationSource();
builder.UpdateConfigurationWithReplace(configSource);
EnterpriseLibraryContainer.Current
= EnterpriseLibraryContainer.CreateDefaultContainer(configSource);
It's also more maintainable and supportable. E.g. there is less chance that there won't be breaking implementation changes like when LogWriter was made abstract as part of version 5.

Categories

Resources