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

时间:2010-02-18 12:33:34

标签: .net vba com app-config

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

我的问题很简单:COM暴露的dll是否有任何方式引用它们各自的配置文件?

示例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];
        }
    }
}

示例VBA:

Public Sub Test()
    Dim Test As New SimpleAppSettingReader
    Dim sampleValue As String
    sampleValue = Test.GetValue("test")
    MsgBox "Value: '" + sampleValue + "'", vbOKOnly
End Sub

6 个答案:

答案 0 :(得分:3)

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

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

我认为您已经建议的是最好的方法。我知道你似乎在复制你的配置文件,这意味着你有重复的东西担心代码何时发生变化,但这是最好的事情。

答案 1 :(得分:3)

我遇到了与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/

答案 2 :(得分:1)

尝试:

ConfigurationManager.OpenExeConfiguration("foo.config");

答案 3 :(得分:1)

您确实可以指定.NET配置API将使用的配置文件,但您必须在创建AppDomain之前执行此操作(这并不像听起来那么简单。)这就是ASP.NET的工作原理例。它将AppDomain设置为使用位于虚拟目录中的“web.config”文件,而不是需要w3p.exe.config或不需要。

您也可以执行此操作,但需要创建辅助AppDomain。由于与多个加载项和程序集引用有关的许多原因,这本身就是一个好主意。但是你可以放在AppDomain's setup中的一件事就是“app.config”文件的名称/路径。

要创建新的AppDomain,您可以使用“shim”,它是一些用于配置和启动AppDomain的样板C ++代码,从那一点开始的其余代码可以是托管代码。

有一篇关于MSDN的文章,由Andrew Whitechapel撰写并称为Isolating Office Extensions with the COM Shim Wizard。我不会撒谎,这不是一个微不足道的概念,但它也不是太糟糕。有一个为您创建C ++项目的向导,它将.NET插件加载到新的AppDomain中。 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文件。

答案 4 :(得分:0)

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

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

答案 5 :(得分:0)

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

它的工作原理如下:

  • 打开dcomcnfg.exe
  • 创建新的COM +应用程序
  • 在“激活”选项卡上的“应用程序根目录”中输入带有com对象的文件夹
  • 将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