Reading custom configuration section from configuration files in COM+

Topics: Building and extending application blocks, General discussion
Aug 4, 2007 at 1:41 AM
Hello everyone,

Here I am writing about a problem that I had and struggled on it for a long time and got it resolved just when I was about to post on codeplex. I thought of posting it because just in case someone has the same issue he/she has somewhere to look it up.

I have a .Net 2.0 DLL being called from the Message Queuing Trigger Service (mqtgsvc.exe) as a COM+ component. This dll is trying to read a configuration file (Application.config) that has along with the out of the box configuration sections (such as loging, ex. handling etc) two custom configuration sections done using Ent. Lib 3.0.

I expose this dll as a COM+ component (using c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\regsvc.exe /appdir:<dir which has all the dll files><mydll.dll>) and register a trigger with the Message Queuing Trigger Service which invokes this component when there is a message on a given queue. Whenever this happens, I am able to retrieve the out of the box sections but the read only fails on the custom sections with the following error.

An error occurred creating the configuration section handler for PRERS.Audit.Configuration: Could not load file or assembly 'PRERS.Audit.Configuration, Version=3.0.24077.0, Culture=neutral, PublicKeyToken=a7e6cac5423f9ea9' or one of its dependencies. The system cannot find the file specified.

with the following stack trace

at System.Configuration.BaseConfigurationRecord.FindAndEnsureFactoryRecord(String configKey, Boolean& isRootDeclaredHere)
at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
at System.Configuration.BaseConfigurationRecord.GetSection(String configKey, Boolean getLkg, Boolean checkPermission)
at System.Configuration.Configuration.GetSection(String sectionName)
at PRERS.Audit.EntityAuditMap.AuditMapConfigBlock.GetConfigSettings() in C:\Projects\PRERS 2007\Main\Source\Audit\Source\PRERS.Audit.EntityAuditMap\AuditMapConfigBlock.cs:line 83
at PRERS.Audit.Business.Utilities.OpenConfig() in C:\Projects\PRERS 2007\Main\Source\Audit\Source\PRERS.Audit.Business\Utilities.cs:line 99
at PRERS.Audit.Business.Utilities.ConvertToAudit(XmlDocument xmlDocument) in C:\Projects\PRERS 2007\Main\Source\Audit\Source\PRERS.Audit.Business\Utilities.cs:line 28
at PRERS.Audit.MSMQTrigger.Auditor.ProcessMessage(Object msgBody) in C:\Projects\PRERS 2007\Main\Source\Audit\Source\PRERS.Audit.MSMQTrigger\Auditor.cs:line 117

I have used the following two methods to read the configuration both of which work and get me my custom configuration sections in my (.Net only) tests.

            string configurationFileFullPath = @"<SoultionPath>\bin\application.config";
            FileConfigurationSource.ResetImplementation(configurationFileFullPath, false);
            FileConfigurationSource fileConfigurationSource = new FileConfigurationSource(configurationFileFullPath);
            AuditMapConfigBlock auditMapConfigBlock = (AuditMapConfigBlock)fileConfigurationSource.GetSection("PRERS.Audit.AuditMapConfigBlock");
            return auditMapConfigBlock;


            string exeFilePath = @"<SoultionPath>\bin\application.config";
            ExeConfigurationFileMap configFile = new ExeConfigurationFileMap();
            configFile.ExeConfigFilename = exeFilePath;
            Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configFile, ConfigurationUserLevel.None);
            AuditMapConfigBlock auditMapConfigBlock = (AuditMapConfigBlock)config.GetSection("PRERS.Audit.AuditMapConfigBlock");
            return auditMapConfigBlock;

Some observations
  1. This configuration file can be read without any problem using the Ent. Lib Configuration Tool (which has the designers for these custom configuration sections). This excludes any possibility of the config file having something miss-spelled or some public key being incorrect.
  2. Also all my VS 2005 tests that I run directly against the .Net assembly (without it being called from the Trigger Service) are able to read the file without any problem. This confirms that the code that is there to read the config file can do it correctly.
  3. I have made sure that all the dependencies for the PRERS.Audit.Configuration .net dll are in memory and I can see them being loaded up in memory in the output box.
  4. I have made sure that the versions are all correct and are signed correctly.
  5. I have an application.manifest file in my bin directory and the COM+ component's "Application Root Directory" is pointing to the bin directory.
  6. Below is the small description of where the binaries are located.
    1. The dll exposed as a COM+ component : <SoultionPath>\bin\
    2. All non-EntLib dlls that the last dll is depending on: <SoultionPath>\bin\
    3. All EntLib dlls : GAC

Can someone tell me what am I missing here ? When all the dependencies and the files required to read the configuration sections are in memory then why am I getting this error ? Are the files being loaded up in one environment (.Net/COM+) and are being accessed in the other which is causing problem ? If yes, then what do I need to do to enable the file load.

So what was missing : Designers + Dlls needed to load the custom sections : GAC

Dhillon, Rupendra
Aug 6, 2007 at 3:34 PM

It really isn't necessary for the designers assemblies to be GAC'd for the runtime to work. As for the custom sections, it shouldn't be necessary either.
Can you try using the fusion log to determine why it cannot get the custom sections' assemblies from the application's folder? I know your application is working now, but forcing assemblies in the GAC when they shouldn't be there is probably not optimal.