代码之家  ›  专栏  ›  技术社区  ›  MPritchard

当通过COM调用app.config时,我可以从.net代码中使用/访问app.config吗

  •  7
  • MPritchard  · 技术社区  · 15 年前

    我有一组现有的.net库,我希望从Excel VBA调用这些库(该部分工作正常)。这些库依赖于app.config中的设置。我知道我可以在excel.exe.config文件中输入这些设置(与excel.exe放在同一个目录中),但对我来说,这似乎不是一个非常易于管理的解决方案,因为我可以看到,如果有多个应用程序想要这样做,就会导致冲突。

    示例app.config:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <appSettings>
        <add key="test" value="Hello world!" />
      </appSettings>
    </configuration>
    

    样本c#:

    namespace ExcelVbaFacingCode
    {
        public class SimpleAppSettingReader
        {
            public string GetValue(string key)
            {
                return ConfigurationManager.AppSettings[key];
            }
        }
    }
    

    Public Sub Test()
        Dim Test As New SimpleAppSettingReader
        Dim sampleValue As String
        sampleValue = Test.GetValue("test")
        MsgBox "Value: '" + sampleValue + "'", vbOKOnly
    End Sub
    
    6 回复  |  直到 15 年前
        1
  •  1
  •   Josh    15 年前

    您也可以这样做,但需要创建辅助AppDomain。这本身就是一个好主意,因为很多原因都与多个外接程序和程序集引用有关。但有一件事你可以放在 AppDomain's setup 是“app.config”文件的名称/路径。

    为了创建新的AppDevices,可以使用一个“SHIM”,它是一个配置和启动AppDe域的样板C++代码,而代码的其余部分可以是托管代码。

    有一篇关于MSDN的文章,由安德鲁·怀特查普撰写,名为 Isolating Office Extensions with the COM Shim Wizard . 我不会撒谎,这不是一个微不足道的概念,但也不是太糟糕。有一个向导为您创建C++项目,它将.NET插件加载到新的AppDe域中。AppDomain的配置必须在加载之前完成,因此您需要将以下内容放入向导创建的代码中。

    // CLRLoader.cpp
    HRESULT CCLRLoader::CreateLocalAppDomain()
    {
    
        ... snip ...
    
        // Configure the AppDomain to use a specific configuration file
        pDomainSetup->put_ConfigurationFile(CComBSTR(szConfigFile));
    
        ... snip ...
    
    }
    

    还值得注意的是,如果/当您转换为VSTO项目时,VSTO运行时会为您执行所有这些AppDomain配置。每个VSTO加载项都在自己的AppDomain中运行,并具有自己的私有app.config文件。

        2
  •  3
  •   Gabriel McAdams    15 年前

    ConfigurationManager.AppSettings 调用时,它会自动打开执行程序集的配置文件。在您的情况下,Excel是正在执行的应用程序,因此您无法打开.Net DLL的配置文件。

    这样做是有原因的。可以从多种类型的应用程序调用单个DLL,每种应用程序可能有不同的需求(例如,可能有不同的数据库)。因此,应用程序指定的是设置,而不是引用的程序集。

    我认为你已经提出的是最好的办法。我知道这似乎是在复制配置文件,这意味着当代码更改时,您需要担心重复的配置文件,但这是最好的做法。

        3
  •  3
  •   Tuomas Hietanen    15 年前

    我在web.config中遇到了类似的问题。。。。我找到了一个有趣的解决办法。您可以封装配置读取功能,例如:

    public class MyClass {
    
    public static Func<string, string> GetConfigValue = s => ConfigurationManager.AppSettings[s];
    
    //...
    
    }
    

    string connectionString = MyClass.GetConfigValue("myConfigValue");
    

    MyClass.GetConfigValue = s =>  s == "myConfigValue" ? "Hi", "string.Empty";
    

    http://rogeralsing.com/2009/05/07/the-simplest-form-of-configurable-dependency-injection/

        4
  •  1
  •   Gary McGill    15 年前

    ConfigurationManager.OpenExeConfiguration("foo.config");
    
        5
  •  0
  •   Anders Abel    15 年前

    据我所知,您希望配置是安装dll的机器的全局配置。机器全局配置选项有一个machine.config文件。我自己从未使用过它,所以我没有任何更详细的信息,但它可能值得研究。 http://msdn.microsoft.com/en-us/library/ms229697(VS.71).aspx . 谷歌搜索“machine.config”会提供更多的信息。

    另一种方法是将自定义xml文件放在dll文件的安装目录中。要获取文件的路径,请使用System.Reflection.Assembly.GetExecutionGassembly.Location(或者使用CodeBase而不是Location)。不幸的是,您必须在xml文件的基础上构建自己的配置管理,但多亏了LINQtoXML,我认为xml比以往任何时候都更加轻松。

        6
  •  0
  •   adrianm    14 年前

    还有一种方法可以从COM组件加载.config文件,我已经使用了好几年了。

    • 打开dcomcnfg.exe
    • 创建新的COM+应用程序
    • 在文件夹中放置一个名为“Application.manifest”的文件。该文件必须包含:

      <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" />

    • 将配置文件放在同一文件夹中。配置文件的名称必须是“Application.config”,即不是“myapp.config”

    您可以使用application.config中的所有普通标记(例如,runtime、system.diagnostics等)


    我使用vbscript创建COM+应用程序:

    Dim allapps, newapp
    Set allapps = objCatalog.GetCollection("Applications")
    
    Set newapp = allapps.Add()
    newapp.Value("Name") = MyComAppName
    newapp.Value("ApplicationAccessChecksEnabled") = False 
    newapp.Value("Activation") = 1 '  own process
    newapp.Value("ApplicationDirectory") = WScript.CreateObject("WScript.Shell").CurrentDirectory
    allapps.SaveChanges
    WScript.Echo "Created application " & ComAppName
    
    objCatalog.ImportComponent ComAppName, MyComName
    WScript.Echo "Installed component " & MyComName