COM Interop Compatibility - A Pipe Dream?

Topics: Building and extending application blocks, Logging Application Block
Feb 2, 2007 at 8:09 PM
I used your Enterprise Library (logging block) with good success on previous projects, and I would like to use if for a current project. Unfortunately this customer is using un-managed code.

I created a class library that accesses the logging application block, and I made a class in the class library com visible so the unmanaged code could call it. However, when the code is run, I get a fatal exception. I realize the logging application block assumes the presence of an application configuration file, but I have re-factored that code to address the problem by accessing a different configuration file.

The code runs without incident when a managed application calls the class libray, but throwd an exception when acceding from un-managed code.

Any help or guidance toward this effort would be greatly appreciated.

The exception I get is:
System.Configuration.ConfigurationErrorsException: An error oc
curred creating the configuration section handler for loggingConfiguration: Coul
d not load file or assembly 'Microsoft.Practices.EnterpriseLibrary.Logging, Vers
ion=2.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. T
he system cannot find the file specified. (C:\Program Files\Microsoft Enterprise
Library January 2006\SimpleTestApp\bin\Debug\Sample_File.config line 4) --->
System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Prac
tices.EnterpriseLibrary.Logging, Version=2.0.0.0, Culture=neutral, PublicKeyToke
n=null' or one of its dependencies. The system cannot find the file specified.
File name: 'Microsoft.Practices.EnterpriseLibrary.Logging, Version=2.0.0.0, Cult
ure=neutral, PublicKeyToken=null'
at System.Configuration.TypeUtil.GetTypeWithReflectionPermission(IInternalCon
figHost host, String typeString, Boolean throwOnError)
at System.Configuration.MgmtConfigurationRecord.CreateSectionFactory(FactoryR
ecord factoryRecord)
at System.Configuration.BaseConfigurationRecord.FindAndEnsureFactoryRecord(St
ring configKey, Boolean& isRootDeclaredHere)

=== Pre-bind state information ===
LOG: User = RADEON\Administrator
LOG: DisplayName = Microsoft.Practices.EnterpriseLibrary.Logging, Version=2.0.0.
0, Culture=neutral, PublicKeyToken=null
(Fully-specified)
LOG: Appbase = file:///C:/WINDOWS/system32/
LOG: Initial PrivatePath = NULL
Calling assembly : System.Configuration, Version=2.0.0.0, Culture=neutral, Publi
cKeyToken=b03f5f7f11d50a3a.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using machine configuration file from C:\WINDOWS\Microsoft.NET\Framework\v2
.0.50727\config\machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partia
l, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/WINDOWS/system32/Microsoft.Practi
ces.EnterpriseLibrary.Logging.DLL.
LOG: Attempting download of new URL file:///C:/WINDOWS/system32/Microsoft.Practi
ces.EnterpriseLibrary.Logging/Microsoft.Practices.EnterpriseLibrary.Logging.DLL.

LOG: Attempting download of new URL file:///C:/WINDOWS/system32/Microsoft.Practi
ces.EnterpriseLibrary.Logging.EXE.
LOG: Attempting download of new URL file:///C:/WINDOWS/system32/Microsoft.Practi
ces.EnterpriseLibrary.Logging/Microsoft.Practices.EnterpriseLibrary.Logging.EXE.


--- End of inner exception stack trace ---
at System.Configuration.BaseConfigurationRecord.FindAndEnsureFactoryRecord(St
ring configKey, Boolean& isRootDeclaredHere)
at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String co
nfigKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Bool
ean requestIsHere, Object& result, Object& resultRuntimeObject)
at System.Configuration.BaseConfigurationRecord.GetSection(String configKey,
Boolean getLkg, Boolean checkPermission)
at System.Configuration.BaseConfigurationRecord.GetSection(String configKey)
at System.Configuration.ConfigurationSectionCollection.Get(String name)
at DigDyn.SimpleLoggerTest.ClassTest.TestThis(String sOverrideConfigFilePat
h, String sectionName) in C:\Program Files\Microsoft Enterprise Library January
2006\Simple_Test\Class1.cs:line 33

The simple class library is:
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.Common;
using System.Text;
using System.Runtime.InteropServices;
using System.Reflection;

namespace DigDyn.SimpleLoggerTest
{
ComVisible(true)
ProgId("DigDyn.SimpleLogTest")
ClassInterface(ClassInterfaceType.AutoDual)
GuidAttribute("747384d1-be9f-4617-be3e-02a7ebd2a35f")
public class Class_Test
{
public Class_Test()
{

}

public bool Test_This(string sOverrideConfigFilePath, string sectionName)
{
ConfigurationSection configurationSection2 = null;

ExeConfigurationFileMap fileMap2 = new ExeConfigurationFileMap();
fileMap2.ExeConfigFilename = sOverrideConfigFilePath;
System.Configuration.Configuration config2 = ConfigurationManager.OpenMappedExeConfiguration(fileMap2, ConfigurationUserLevel.None);

try
{
configurationSection2 = config2.Sections.Get(sectionName);
}
catch (Exception ex)
{
System.Console.WriteLine("Exception Caught: " + ex.ToString());
}

if (configurationSection2 == null)
{
return false;
}
else
{
return true;
}
}
}
}

My config file:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
<section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
</configSections>
<loggingConfiguration name="Logging Application Block" tracingEnabled="true"
defaultCategory="General" logWarningsWhenNoCategoriesMatch="true">
<listeners>
<add fileName="STANDARD_.log" header="----------------------------------------"
footer="----------------------------------------" formatter=""
listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"
traceOutputOptions="None" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"
name="FlatFile TraceListener" />
</listeners>
<formatters>
<add template="Timestamp: {timestamp}&#xD;&#xA;Message: {message}&#xD;&#xA;Category: {category}&#xD;&#xA;Priority: {priority}&#xD;&#xA;EventId: {eventid}&#xD;&#xA;Severity: {severity}&#xD;&#xA;Title:{title}&#xD;&#xA;Machine: {machine}&#xD;&#xA;Application Domain: {appDomain}&#xD;&#xA;Process Id: {processId}&#xD;&#xA;Process Name: {processName}&#xD;&#xA;Win32 Thread Id: {win32ThreadId}&#xD;&#xA;Thread Name: {threadName}&#xD;&#xA;Extended Properties: {dictionary({key} - {value}&#xD;&#xA;)}"
type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"
name="Text Formatter" />
</formatters>
<categorySources>
<add switchValue="All" name="General">
<listeners>
<add name="FlatFile TraceListener" />
</listeners>
</add>
</categorySources>
<specialSources>
<allEvents switchValue="All" name="All Events" />
<notProcessed switchValue="All" name="Unprocessed Category" />
<errors switchValue="All" name="Logging Errors & Warnings">
<listeners>
<add name="FlatFile TraceListener" />
</listeners>
</errors>
</specialSources>
</loggingConfiguration>
</configuration>
Feb 2, 2007 at 9:25 PM
I have corrected this issue, the calling application cscript.exe was unable to locate the assembly, but when moved to the same location, success.