我有一个自定义的 .Net dll 组件,它将通过 COM 互操作从 MS Access 调用。
因为 MSACCESS.EXE 是调用进程,默认情况下它将尝试在安装 MS Access 的位置定位程序集 .config 文件和任何引用的 ddls。
由于部署问题,我们希望所有自定义代码从单独的位置运行,而不是从 MS Office 文件夹结构中运行。
我已经能够使用以下方法强制程序集从自定义位置加载其配置信息:
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);
这似乎工作正常,除日志记录外,此时一切似乎都正常。无论如何,log4net.dll 文件不会从 MSACCESS.EXE 所在目录以外的任何位置加载。
我尝试将以下内容添加到我的 app.config 文件中(log4net.dll 与我的 .Net 组件位于同一目录中),但它似乎被忽略了。
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="c:\mycomponent" />
</assemblyBinding>
</runtime>
我使用 SysInternals procmon 来确认从 Access 调用组件时是否找到了 dll,并且它已成功定位,但随后它恢复为尝试从 MS Access 目录加载它并失败。
无论如何强制log4net.dll从我想要的位置加载?
这是 log4net 内部调试日志的输出:
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)