C# Windows 服务无法将 GetSection() 与自定义 ConfigurationSection 一起使用

C# Windows Service can not use GetSection() with custom ConfigurationSection

我在 Windows 服务中尝试使用自定义 app.config 部分时遇到异常。我已经成功地在其他应用程序中编写了自定义部分,所以很确定我的机制是正确的,并且当涉及到 Windows 服务时就会发生一些事情。如果需要,我可以包含 app.config Xml。

第一次尝试

我在 C# windows 服务构造函数中有以下代码:

int systemErrorWindowSeconds = 
    ServiceSettings.Current.ExceptionHandling.SystemErrorWindowSeconds;

而ServiceSettings(重要的位)如下:

public class ServiceSettings : ConfigurationSection
{
    private static ServiceSettings settings;

    static ServiceSettings()
    {
        var config = 
            ConfigurationManager.OpenExeConfiguration( ConfigurationUserLevel.None );

        settings = config.GetSection( "serviceSettings" ) as ServiceSettings;
    }

    public static ServiceSettings Current { get { return settings;  } }

当我尝试访问 ServiceSettings.Current 时出现以下异常:

Application: BTR.Evolution.Service.exe  
Framework Version: v4.0.30319  
Description: The process was terminated due to an unhandled exception. 
Exception Info:    System.Configuration.ConfigurationErrorsException
    at System.Configuration.BaseConfigurationRecord.EvaluateOne(System.String[], System.Configuration.SectionInput, Boolean, System.Configuration.FactoryRecord, System.Configuration.SectionRecord, System.Object)
    at System.Configuration.BaseConfigurationRecord.Evaluate(System.Configuration.FactoryRecord, System.Configuration.SectionRecord, System.Object, Boolean, Boolean, System.Object ByRef, System.Object ByRef)
    at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(System.String, Boolean, Boolean, Boolean, Boolean, System.Object ByRef, System.Object ByRef)
    at System.Configuration.Configuration.GetSection(System.String)
    at BTR.Evolution.Service.ServiceSettings..cctor() Exception Info: System.TypeInitializationException
    at BTR.Evolution.Service.ServiceSettings.get_Current()
    at BTR.Evolution.Service.EvolutionService..ctor(System.String[])
    at BTR.Evolution.Service.Program.Main(System.String[])

第二次尝试:

我更改了 ServiceSettings class 以使用 GetSection,例如:

static ServiceSettings()
{
    settings = ConfigurationManager.GetSection( "serviceSettings" ) as ServiceSettings;
}

我得到以下异常(大部分与上面相同,但使用 ConfigurationManager 和更多的 GetSectionRecursive 调用)

Application: BTR.Evolution.Service.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: 
  System.Configuration.ConfigurationErrorsException
    at System.Configuration.BaseConfigurationRecord.EvaluateOne(System.String[], System.Configuration.SectionInput, Boolean, System.Configuration.FactoryRecord, System.Configuration.SectionRecord, System.Object)
    at System.Configuration.BaseConfigurationRecord.Evaluate(System.Configuration.FactoryRecord, System.Configuration.SectionRecord, System.Object, Boolean, Boolean, System.Object ByRef, System.Object ByRef)
    at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(System.String, Boolean, Boolean, Boolean, Boolean, System.Object ByRef, System.Object ByRef)
    at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(System.String, Boolean, Boolean, Boolean, Boolean, System.Object ByRef, System.Object ByRef)
    at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(System.String, Boolean, Boolean, Boolean, Boolean, System.Object ByRef, System.Object ByRef)
    at System.Configuration.BaseConfigurationRecord.GetSection(System.String)
    at System.Configuration.ClientConfigurationSystem.System.Configuration.Internal.IInternalConfigSystem.GetSection(System.String)
    at System.Configuration.ConfigurationManager.GetSection(System.String)
    at BTR.Evolution.Service.ServiceSettings..cctor() Exception Info: System.TypeInitializationException
    at BTR.Evolution.Service.ServiceSettings.get_Current()
    at BTR.Evolution.Service.EvolutionService..ctor(System.String[])
    at BTR.Evolution.Service.Program.Main(System.String[])

第三次尝试

我更改了 ServiceSettings 构造函数以尝试:

var customConfig = 
    ConfigurationManager.OpenExeConfiguration( AppDomain.CurrentDomain.SetupInformation.ConfigurationFile );

settings = customConfig.GetSection( "serviceSettings" ) as ServiceSettings;

我得到了以下异常。基本上,设置变量被分配给 null(没有 'configuration manager' 异常)所以使用该对象的调用者得到一个 null 异常。

Application: BTR.Evolution.Service.exe
Framework Version: v4.0.30319 
Description: The process was terminated due to an unhandled exception. 
Exception Info: System.NullReferenceException 
    at BTR.Evolution.Service.EvolutionService..ctor(System.String[]) 
    at BTR.Evolution.Service.Program.Main(System.String[])

最后的尝试

我更改了 ServiceSettings 构造函数以尝试使用程序集解析器。

Func<object, ResolveEventArgs, System.Reflection.Assembly> getAssembly = 
    ( sender, args ) => typeof( ServiceSettings ).Assembly;

var resolveHandler = new System.ResolveEventHandler( getAssembly );

AppDomain.CurrentDomain.AssemblyResolve += resolveHandler;

var customConfig = 
    ConfigurationManager.OpenExeConfiguration( AppDomain.CurrentDomain.SetupInformation.ConfigurationFile );

settings = customConfig.GetSection( "serviceSettings" ) as ServiceSettings;

AppDomain.CurrentDomain.AssemblyResolve -= resolveHandler;

但是我得到了与第三次尝试完全相同的结果。

任何关于如何使这项工作的建议将不胜感激。如果我需要提供任何其他信息,请告诉我。

嗯,有点不好意思。我按照建议使用相同的代码和设置制作了一个新的控制台应用程序并且它有效。所以 re-examined 我的 Windows 服务和我试图使用自定义程序集解析器来定位配置 file/section。我假设当我最初编写服务时遇到了问题并且我尝试了这个自定义解析器(仍然没有用)。那是我发布这个问题的时候。但不管怎样,我只放回标准 ConfigurationManager.GetSection(上面的第二种方法)机制来获取自定义部分并且它起作用了。无法解释