繁体   English   中英

从备用位置加载log4net.dll

[英]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)

我以前用过这样的东西。 不过,有些注意事项:

  • 这是非常通用的,因此可以根据需要随时对其进行修改
  • 如果版本冲突(例如,主应用程序使用log4net 2.0,而您的应用程序使用log4net 3.0),则可能会混淆AppDomain。

码:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM