I have a custom .Net dll component that will be called from MS Access via COM Interop.
Because MSACCESS.EXE is the calling process, it will by default attempt to locate the assemblies .config file, and any referenced ddls, at the location where MS Access is installed.
Because of deployment concerns, we want all of the custom code to run from a separate location, not from within the MS Office folder structure.
I've been able to force the assembly to load it's configuration information from a custom location using:
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", customPath);
typeof(ConfigurationManager)
.GetField("s_initState", BindingFlags.NonPublic |
BindingFlags.Static)
.SetValue(null, 0);
typeof(ConfigurationManager)
.GetField("s_configSystem", BindingFlags.NonPublic |
BindingFlags.Static)
.SetValue(null, null);
typeof(ConfigurationManager)
.Assembly.GetTypes()
.Where(x => x.FullName ==
"System.Configuration.ClientConfigPaths")
.First()
.GetField("s_current", BindingFlags.NonPublic |
BindingFlags.Static)
.SetValue(null, null);
That seems to work fine and everything seems to work at this point except logging. No matter what, the log4net.dll file will not load from any location other than the directory where MSACCESS.EXE is located.
I tried adding the following to my app.config file (log4net.dll is in the same directory as my .Net component) but it seems to be ignored.
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="c:\mycomponent" />
</assemblyBinding>
</runtime>
I used SysInternals procmon to confirm that the dll is being found when the component is called from Access, and it is successfully located, but then it reverts to trying to load it from the MS Access directory and fails.
Is there anyway to force log4net.dll to load from the location that I want?
Here's the output from the log4net internal debug log:
log4net:ERROR Failed to parse config file. Is the <configSections> specified as: <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net, Version=1.2.11.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a" />
System.Configuration.ConfigurationErrorsException: An error occurred creating the configuration section handler for log4net: Could not load file or assembly 'log4net' or one of its dependencies. The system cannot find the file specified. (C:\mycomponent\alt.config line 4) ---> System.IO.FileNotFoundException: Could not load file or assembly 'log4net' or one of its dependencies. The system cannot find the file specified.
at System.Configuration.TypeUtil.GetTypeWithReflectionPermission(IInternalConfigHost host, String typeString, Boolean throwOnError)
at System.Configuration.RuntimeConfigurationRecord.RuntimeConfigurationFactory.Init(RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord)
at System.Configuration.RuntimeConfigurationRecord.RuntimeConfigurationFactory.InitWithRestrictedPermissions(RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord)
at System.Configuration.RuntimeConfigurationRecord.CreateSectionFactory(FactoryRecord factoryRecord)
at System.Configuration.BaseConfigurationRecord.FindAndEnsureFactoryRecord(String configKey, Boolean& isRootDeclaredHere)
--- End of inner exception 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)
at System.Configuration.ClientConfigurationSystem.System.Configuration.Internal.IInternalConfigSystem.GetSection(String sectionName)
at System.Configuration.ConfigurationManager.GetSection(String sectionName)
at System.Configuration.ConfigurationSettings.GetConfig(String sectionName)