【问题标题】:TypeInitializationException in NLog LoggerFactoryNLog LoggerFactory 中的 TypeInitializationException
【发布时间】:2018-06-11 14:29:12
【问题描述】:

我开发了一个使用 NLog 的 WPF 应用程序。它已部署给一些潜在客户,其中一个应用程序运行良好一周,现在甚至无法打开。也就是说,您双击应用程序图标,实际上什么也没有发生。甚至没有 AppDomain.CurrentDomain.UnhandledException catch 子句中的日志记录。

我能够在 Windows 事件查看器中识别一个事件(请参阅下面的消息)。

让我感到困扰的是在一周的完美操作后突然出现此错误,并且我无法解释此消息或在线查找有关它的信息。

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[])

这是我的 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");
    }
}

更新(包含其他可能相关的信息):

有人提到了NLog XML配置文件,但我使用的是运行时配置,如下:

        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;

此外,“堆栈跟踪”(在 Windows 事件的情况下似乎是向后打印的)表明 NLog 本身正在从 System.Configuration 类中获取异常,从 InternalLogger 的反编译中可以看出:

命名空间 NLog.Common { //... 公共静态类 InternalLogger { //... 私有静态字符串 GetSettingString(string configName, string envName) { // 下面的行似乎正在抛出异常 字符串 str = System.Configuration.ConfigurationManager.AppSettings[configName]; //..

【问题讨论】:

  • 您使用的是什么记录器(nlog 配置)?可能是一些权限问题导致了这种情况吗?是什么导致了System.Xml.XmlException
  • 猜测,其中一个 Xml 配置文件(例如 App.exe.config)已损坏?
  • @StuartLC 我同意这似乎是问题所在。但那又如何呢?我想知道是什么导致了这个问题,一方面,另一方面,我不知道应该如何纠正/预防这个问题。另外我不确定我应该如何调试它,因为问题只表现在我们只能远程访问的客户端机器上。
  • 原因可能是用户摆弄、病毒、磁盘故障等如果胖/智能客户端的风险??

标签: c# exception nlog typeinitializeexception


【解决方案1】:

您的 NLog (XML) 配置中可能存在配置错误。

那么,为什么您会收到 TypeInitializationException 而不是有用的消息?那是因为您在启动程序之前初始化了 NLog。行:

static readonly Logger logger = LogManager.GetLogger(typeof(App).FullName);

将在Main 之前运行,因为它是一个静态字段。不幸的是,NLog 不能抛出更好的异常(参见:Better TypeInitializationException (innerException is also null)

建议:在这种情况下,建议使用非静态 Logger,或者,static Lazy<Logger>

static readonly Lazy<Logger> logger = new Lazy<Logger>(() => LogManager.GetLogger(typeof(App).FullName));

【讨论】:

  • 感谢您的回答。通过静态惰性记录器,您的意思是这样的吗? private static readonly Lazy&lt;Logger&gt; logger = new Lazy&lt;Logger&gt;(() =&gt; LogManager.GetLogger(typeof(App).FullName));
  • 我意识到我没有为 NLog 使用 XML 配置,而是在代码本身中执行配置(我知道这并不理想,但现在就是这样)。此外,似乎原始异常可能是由.Net 类引起的,特别是System.Configuration.ConfigurationManager.AppSettings,它抛出了ConfigurationErrorsException。 (查看我的更新)
  • 所以你的问题解决了不是吗?你知道根本原因吗?
  • 嗯,实际上不是,但我想这不完全是 NLog 错误。我想我必须进一步调查为什么首先会发生`ConfigurationErrorsException。无论如何,感谢您的回复!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-21
  • 1970-01-01
  • 2013-11-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多