Cannot Initialize Config from Windows Service?

Topics: Logging Application Block
Aug 10, 2010 at 8:32 PM

I have created a Windows Service that uses a DLL that wrappers calls to the Logging Application (which I tested using a console application).  When I try to start the service I get an exception on this factory line:

        private LogWriter logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();

which is generating the following exception:

Log Name:      Application
Source:        .NET Runtime
Date:          08/10/2010 04:06:15 PM
Event ID:      1026
Task Category: None
Level:         Error
Keywords:      Classic
User:          N/A
Computer:      MDRNDEPI27267.BDX.com
Description:
Application: EpiCenterInstrumentInterface.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.Configuration.ConfigurationErrorsException
Stack:
   at System.Configuration.ClientConfigurationSystem.EnsureInit(System.String)
   at System.Configuration.ClientConfigurationSystem.PrepareClientConfigSystem(System.String)
   at System.Configuration.ClientConfigurationSystem.System.Configuration.Internal.IInternalConfigSystem.GetSection(System.String)
   at System.Configuration.ConfigurationManager.GetSection(System.String)
   at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ConfigurationSourceFactory.Create()
   at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.EnterpriseLibraryContainer.SetCurrentContainerIfNotSet()
   at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.EnterpriseLibraryContainer.get_Current()
   at BD.EpiCenter.Logging.clsEpiCenterLogger..ctor()
   at BD.EpiCenter.EpiCenterInstrumentInterface.clsInstrumentInterfaceService..ctor()
   at BD.EpiCenter.EpiCenterInstrumentInterface.Program.Main(System.String[])

Event Xml:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
  <System>
    <Provider Name=".NET Runtime" />
    <EventID Qualifiers="0">1026</EventID>
    <Level>2</Level>
    <Task>0</Task>
    <Keywords>0x80000000000000</Keywords>
    <TimeCreated SystemTime="2010-08-10T20:06:15.000000000Z" />
    <EventRecordID>59366</EventRecordID>
    <Channel>Application</Channel>
    <Computer>MDRNDEPI27267.BDX.com</Computer>
    <Security />
  </System>
  <EventData>
    <Data>Application: EpiCenterInstrumentInterface.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.Configuration.ConfigurationErrorsException
Stack:
   at System.Configuration.ClientConfigurationSystem.EnsureInit(System.String)
   at System.Configuration.ClientConfigurationSystem.PrepareClientConfigSystem(System.String)
   at System.Configuration.ClientConfigurationSystem.System.Configuration.Internal.IInternalConfigSystem.GetSection(System.String)
   at System.Configuration.ConfigurationManager.GetSection(System.String)
   at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ConfigurationSourceFactory.Create()
   at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.EnterpriseLibraryContainer.SetCurrentContainerIfNotSet()
   at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.EnterpriseLibraryContainer.get_Current()
   at BD.EpiCenter.Logging.clsEpiCenterLogger..ctor()
   at BD.EpiCenter.EpiCenterInstrumentInterface.clsInstrumentInterfaceService..ctor()
   at BD.EpiCenter.EpiCenterInstrumentInterface.Program.Main(System.String[])
</Data>
  </EventData>
</Event>

I'm assuming there is an issue with GetInstance but not sure how to overcome it for the Windows Servce.

Aug 11, 2010 at 12:29 AM

Does your windows service's configuration file contains the loggingConfiguration section?

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

Aug 11, 2010 at 12:21 PM

The service calls out to a wrapper DLL that encapsulates the calls to the logging application block.  I am employing the externally referenced config trick for the DLL and the config for the service iteself looks like:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key = "Port" value = "10005"/>
    <add key = "Use Loopback" value = "True"/>
    <add key = "Debug Tracing" value = "True"/>
    <add key ="DuplicateTestWindow" value="30"/>
  </appSettings> 
  <configSections>
    <section name="enterpriseLibrary.ConfigurationSource" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ConfigurationSourceSection, Microsoft.Practices.EnterpriseLibrary.Common, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
  </configSections>
  <enterpriseLibrary.ConfigurationSource selectedSource="File-based Configuration Source">
    <sources>
      <add name="File-based Configuration Source" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        filePath="C:\Program Files (x86)\Becton Dickinson\EpiCenter\Log\Extern.config" />
    </sources>
  </enterpriseLibrary.ConfigurationSource>
</configuration>

Aug 11, 2010 at 8:10 PM

Tried to restructure a bit based on some things I've read here in the discussions and came up with the following code for my service:

        private LogWriter _logWriter = null;

        /// <summary>
        /// clsEpiCenterLogger
        /// </summary>
        public clsEpiCenterLogger()
        {
            if (_logWriter == null)
            {
                try
                {
                    _logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
                }
                catch (Microsoft.Practices.ServiceLocation.ActivationException)
                {
                    //
                    // 
                    //
                    string configFilename = @"C:\Program Files (x86)\Becton Dickinson\EpiCenter\Log\EpiLogging.xml";

                    FileConfigurationSource epiLogConfigSource = new FileConfigurationSource(configFilename);
                    EnterpriseLibraryContainer.Current = EnterpriseLibraryContainer.CreateDefaultContainer(epiLogConfigSource);

                    _logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
                }
            }
        }

But the service still fails to start and throws the exception:

Application: EpiCenterInstrumentInterface.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.Configuration.ConfigurationErrorsException
Stack:
   at System.Configuration.ClientConfigurationSystem.EnsureInit(System.String)
   at System.Configuration.ClientConfigurationSystem.PrepareClientConfigSystem(System.String)
   at System.Configuration.ClientConfigurationSystem.System.Configuration.Internal.IInternalConfigSystem.GetSection(System.String)
   at System.Configuration.ConfigurationManager.GetSection(System.String)
   at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ConfigurationSourceFactory.Create()
   at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.EnterpriseLibraryContainer.SetCurrentContainerIfNotSet()
   at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.EnterpriseLibraryContainer.get_Current()
   at BD.EpiCenter.Logging.clsEpiCenterLogger..ctor()
   at BD.EpiCenter.EpiCenterInstrumentInterface.clsInstrumentInterfaceService..ctor()
   at BD.EpiCenter.EpiCenterInstrumentInterface.Program.Main(System.String[])

 

I have tested this code with a console application which seems to work fine:

using System;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging;

namespace TestConfiguration
{
    class Program
    {
        static void Main(string[] args)
        {
            string configFilename = @"C:\Program Files (x86)\Becton Dickinson\EpiCenter\Log\EpiLogging.xml";

            FileConfigurationSource epiLogConfigSource = new FileConfigurationSource(configFilename);
            EnterpriseLibraryContainer.Current = EnterpriseLibraryContainer.CreateDefaultContainer(epiLogConfigSource);

            LogWriter _logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();


            LogEntry logEntry = new LogEntry();

            string traceTxt = string.Format("{0} Testing...",  DateTime.Now.ToString());
            logEntry.Message = traceTxt;
            logEntry.Categories.Add("EpiCenter Log");
            logEntry.Priority = 2;
            _logWriter.Write(logEntry);


            Console.ReadLine();
        }
    }
}

Both using the same config file of course:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
    </configSections>
    <loggingConfiguration name="" tracingEnabled="true" defaultCategory="Event Log">
        <listeners>
            <add name="Event Log Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FormattedEventLogTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FormattedEventLogTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                source="BDEpiCenterSource" formatter="Text Formatter" log="BDEpiCenterLog"
                machineName="." traceOutputOptions="None" />
            <add name="Flat File Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                fileName="trace.log" formatter="Text Formatter" />
            <add name="Rolling Flat File Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.RollingFlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.RollingFlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                fileName="%ProgramFiles(x86)%\Becton Dickinson\EpiCenter\Log\EpiCenterLog.log"
                footer="---" formatter="Epi Formatter" header="+++" rollFileExistsBehavior="Increment"
                rollSizeKB="10" maxArchivedFiles="10" />
        </listeners>
        <formatters>
            <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                template="Timestamp: {timestamp}{newline}&#xA;Message: {message}{newline}&#xA;Category: {category}{newline}&#xA;Priority: {priority}{newline}&#xA;EventId: {eventid}{newline}&#xA;Severity: {severity}{newline}&#xA;Title:{title}{newline}&#xA;Machine: {localMachine}{newline}&#xA;App Domain: {localAppDomain}{newline}&#xA;ProcessId: {localProcessId}{newline}&#xA;Process Name: {localProcessName}{newline}&#xA;Thread Name: {threadName}{newline}&#xA;Win32 ThreadId:{win32ThreadId}{newline}&#xA;Extended Properties: {dictionary({key} - {value}{newline})}"
                name="Text Formatter" />
            <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                template="{message}" name="Epi Formatter" />
        </formatters>
        <categorySources>
            <add switchValue="All" name="Event Log">
                <listeners>
                    <add name="Event Log Listener" />
                </listeners>
            </add>
            <add switchValue="ActivityTracing" name="Trace">
                <listeners>
                    <add name="Flat File Trace Listener" />
                </listeners>
            </add>
            <add switchValue="All" name="EpiCenter Log">
                <listeners>
                    <add name="Rolling Flat File Trace Listener" />
                </listeners>
            </add>
        </categorySources>
        <specialSources>
            <allEvents switchValue="All" name="All Events" />
            <notProcessed switchValue="All" name="Unprocessed Category" />
            <errors switchValue="All" name="Logging Errors &amp; Warnings">
                <listeners>
                    <add name="Event Log Listener" />
                </listeners>
            </errors>
        </specialSources>
    </loggingConfiguration>
</configuration>
Aug 11, 2010 at 11:08 PM

Are you hitting this known issue by any chance?

Aug 12, 2010 at 1:09 PM

Possibly but I just removed all references to the Entlib from the service's app.config and use this code in my logger DLL and I am able to run without issue.

       private LogWriter _logWriter = null;

        /// <summary>
        /// clsEpiCenterLogger
        /// </summary>
        public clsEpiCenterLogger()
        {
            if (_logWriter == null)
            {
                try
                {
                    _logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
                }
                catch (Microsoft.Practices.ServiceLocation.ActivationException)
                {
                    //
                    // 
                    //
                    string configFilename = @"C:\Program Files (x86)\Becton Dickinson\EpiCenter\Log\EpiLogging.xml";

                    FileConfigurationSource epiLogConfigSource = new FileConfigurationSource(configFilename);
                    EnterpriseLibraryContainer.Current = EnterpriseLibraryContainer.CreateDefaultContainer(epiLogConfigSource);

                    _logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
                }
            }
        }


With EpiLogging.xml containing all the entlib logging configuration settings.
Aug 13, 2010 at 3:37 AM

Yes, it really looks like you're encountering that issue.  The code works because you specified a full path instead of a relative path.

If you want to be able to specify a relative path, you can create a custom configuration source.  Basically, you'll just copy the code of entlib's FileConfigurationSource

and implement the code fix for the GetRootedConfigurationFile method posted in the work item in the issue tracker.   

You'll also be able to provide integration of your custom configuration source in the configuration tool.  A discussion about this can be found in this thread

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com