[英]Load log4net.dll from alternate location
我有一个自定义.Net dll组件,该组件将从MS Access通过COM Interop调用。
由于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,并且已成功定位该dll,但是随后恢复为尝试从MS Access目录加载该dll并失败。
无论如何有强制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)
我以前用过这样的东西。 不过,有些注意事项:
码:
class AssemblyResolver
{
static AssemblyResolver()
{
AppDomain.CurrentDomain.AssemblyResolve +=
(sender, args) =>
{
var referencedAssemblies = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
var instanceName = referencedAssemblies.ToList().First(x => x.FullName == args.Name).Name;
var loadFile = Assembly.LoadFile(System.IO.Path.GetDirectoryName(Assembly.GetAssembly(typeof(AssemblyResolver)).Location) + @"\" + instanceName + ".dll");
return loadFile;
};
}
public AssemblyResolver()
{
}
}
然后,要使用此功能,只需加载AssemblyResolver
。 它的静态构造函数将处理维护
实例化代码时的第一件事:
new AssemblyResolver()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.