ConfigurationManager.OpenMappedExeConfiguration问题

时间:2014-12-10 13:08:23

标签: c# .net config .net-assembly configuration-files

我有这个类库被加载到第三方系统。我多年来一直使用自定义配置,并通过ConfigurationManager.OpenMappedExeConfiguration()访​​问它们,因为这总是允许我将配置文件与dll相关联,并避免必须修改第三方系统配置文件。我们目前正在升级系统,现在这不起作用。这个例外给我的印象是它通过在主持人exe位置开始探测程序集。我的组件存放在一个单独的位置,以避免我的所有东西与他们混合(更容易维护,因为我们有一组非常多样化的组件)。我发现通过将程序集及其配置放在exe的主安装目录中它确实有效,所以我认为绑定是这一天的问题,但就像我说我宁愿避免将我的所有内容复制到那个目录。这可能是关于如何将程序集加载到系统中的问题吗? ConfigurationManager的代码库是否有变化?那么远程访问配置文件的方法是什么呢?

我在他们的网站上发布了一个论坛问题,但我想在这里发布一些内容,以防有人知道.NET解决方法并不需要了解第三方系统API(AutoCAD 2015)。这是我得到的例外,它看起来像某种约束问题。也许他们已经改变了我们的程序集加载到系统的方式?他们做了几次安全性更改,所以我猜这是可能的。

  

发现了System.IO.FileNotFoundException     _HResult = -2147024894     _message =无法加载文件或程序集' TestAutoCADApp,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'或其中一个依赖项。该系统找不到指定的文件。     的HResult = -2147024894     IsTransient = FALSE     消息=无法加载文件或程序集' TestAutoCADApp,版本= 1.0.0.0,Culture = neutral,PublicKeyToken = null'或其中一个依赖项。该系统找不到指定的文件。     来源= System.Configuration     FileName = TestAutoCADApp,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null

     

FusionLog ====预绑定状态信息===   日志:DisplayName = TestAutoCADApp,版本= 1.0.0.0,Culture = neutral,PublicKeyToken = null    (完全指定的)   日志:Appbase = file:/// C:/ Program Files / Autodesk / AutoCAD 2015 /   日志:初始PrivatePath = NULL

     

调用程序集:System.Configuration,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a。

     

日志:此绑定在默认加载上下文中启动。   日志:使用应用程序配置文件:C:\ Program Files \ Autodesk \ AutoCAD 2015 \ acad.exe.Config   日志:使用主机配置文件:   日志:使用C:\ Windows \ Microsoft.NET \ Framework64 \ v4.0.30319 \ co nfig \ machine.config中的计算机配置文件。   日志:此时策略未应用于引用(私有,自定义,部分或基于位置的程序集绑定)。   日志:尝试下载新的URL文件:/// C:/ Program Files / Autodesk / AutoCAD 2015 / TestAutoCADApp.DLL。   日志:尝试下载新的URL文件:/// C:/ Program Files / Autodesk / AutoCAD 2015 / TestAutoCADApp / TestAutoCADApp.DLL。   日志:尝试下载新的URL文件:/// C:/ Program Files / Autodesk / AutoCAD 2015 / TestAutoCADApp.EXE。   日志:尝试下载新的URL文件:/// C:/ Program Files / Autodesk / AutoCAD 2015 / TestAutoCADApp / TestAutoCADApp.EXE。

     

堆栈跟踪:          at System.Configuration.TypeUtil.GetTypeWithReflectio nPermission(IInternalConfigHost host,String typeString,Boolean throwOnError)          在System.Configuration.MgmtConfigurationRecord.Creat eSectionGroupFactory(FactoryRecord factoryRecord)          在System.Configuration.MgmtConfigurationRecord.Ensur eSectionGroupFactory(FactoryRecord factoryRecord)          在System.Configuration.MgmtConfigurationRecord.GetSe ctionGroup(String configKey)          在System.Configuration.Configuration.GetSectionGroup(String sectionGroupName)          at TestAutoCADApp.Commands.TestConfigSettingsAccess(A ction`1 writeAction)在c:\ Development-TVA \ Visual Studio 2013 \ TestCode \ TestAutoCADApp \ TestAutoCADApp \ Comman ds.cs:第49行     的InnerException:

我可以显示自定义配置代码,但是如果您不熟悉系统,那么它对您没有任何好处。所以现在,这是一个非常通用的例子,说明我如何访问它,现在已经有一段时间了。

  Uri uriCodeBase = new Uri(Assembly.GetExecutingAssembly().CodeBase);
  FileInfo appfilePath = new FileInfo(uriCodeBase.LocalPath + ".config");

  ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
  fileMap.ExeConfigFilename = appfilePath.FullName;

  Configuration configuration = null;

  //Retrieve the Configuration file data and return
  configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

  MainGroup mainGroup = configuration.GetSectionGroup("mainGroup") as MainGroup;

  MainSection mainSection = mainGroup.Sections["mainSection"] as MainSection;

  SomeElement someElement = mainSection.SomeElement;

1 个答案:

答案 0 :(得分:2)

好吧,我终于从供应商那里听到了,结果发现他们曾经在他们的API中处理AssemblyResolve事件,如果在加载主dll时发生问题,就会解决加载辅助dll的问题。他们显然遇到了这个问题,并决定将其与最新版本一起推出。他们建议我通过自己注册活动来处理这个问题并使用以下代码(对于那些对此问题也感兴趣的人)。

在原始问题中显示的代码中,在开头添加:

AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;

事件代表:

    Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        Assembly assembly = null;
        Assembly[] assems = AppDomain.CurrentDomain.GetAssemblies();
        String name;
        if (args.Name.IndexOf(",") > -1)
            name = args.Name.Substring(0, args.Name.IndexOf(","));
        else
            name = args.Name;

        foreach (Assembly assem in assems)
        {
            if (assem.GetName().Name == name)
            {
                return assem;
            }
        }

        return assembly;
    }

我希望这比它更有意义,但我猜测ConfigurationManager必须尝试访问dll,就像它是辅助dll一样,以便它可以读取和合并配置文件。它必须探测装配和失败。但这只是我的猜测。我不确定。无论哪种方式,实现此方法都会导致正确的程序集在失败时返回。