Я могу использовать / получают доступ к app.config из кода .NET при вызове через COM

У меня есть существующий набор библиотек .NET, которые я хочу назвать от Excel VBA (что часть хорошо работает). Эти библиотеки полагаются на настройки в app.config. Я знаю, что могу ввести эти настройки в excel.exe.config файл (помещенный в тот же каталог как excel.exe), но это действительно не походит на очень управляемое решение меня, поскольку я вижу порождение конфликтов, если больше чем одно приложение хочет сделать это.

Мой вопрос прост: есть ли какой-либо способ выставленного dlls COM, обращающегося к их соответствующим файлам конфигурации?

Образец 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
7
задан MPritchard 18 February 2010 в 14:44
поделиться

5 ответов

Вы действительно можете указать файл конфигурации, который будет использоваться API конфигурации .NET, но вы должны сделать это до создания AppDomain (что не так просто, как кажется). Вот как, например, работает ASP.NET. Он настраивает AppDomain на использование файла "web.config", расположенного в виртуальном каталоге, в отличие от требуемого w3p.exe.config или чего-либо еще.

Вы тоже можете так сделать, но вам нужно создать вторичный AppDomain. Это сама по себе хорошая идея по многим причинам, связанным с множественными дополнениями и ссылками на сборки. Но одна из вещей, которую вы можете указать в настройках AppDomain'а - это имя/путь файла "app.config".

Для создания нового AppDomain вы можете использовать "shim", который является небольшим кодом на C++, который конфигурирует и запускает AppDomain, а остальной код с этого момента может быть управляемым кодом.

На MSDN есть статья, написанная Эндрю Уайтчапелом и называющаяся Изоляция расширений Office с помощью мастера COM Shim Wizard. Не буду врать, это не тривиальная концепция, но и не слишком плохая. Есть мастер, который создает для вас проект C++, который загружает .NET addin в новый 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.

1
ответ дан 7 December 2019 в 05:21
поделиться

Попробуйте:

ConfigurationManager.OpenExeConfiguration("foo.config");
1
ответ дан 7 December 2019 в 05:21
поделиться

При каждом вызове ConfigurationManager.AppSettings автоматически открывается конфигурационный файл исполняющей сборки. В вашем случае исполняющим приложением является Excel, поэтому вы не можете открыть файл конфигурации .Net DLL.

Это было сделано не просто так. Одна DLL может быть вызвана из нескольких типов приложений, каждое из которых может иметь различные требования (и, возможно, различные базы данных, например). По этой причине приложение задает настройки, а не ссылающаяся сборка.

Я думаю, что то, что вы уже предложили, - лучший способ сделать это. Я знаю, что это похоже на копирование файла конфигурации, и что это означает, что у вас есть дубликаты, о которых нужно беспокоиться при изменении кода, но это лучшее, что можно сделать.

3
ответ дан 7 December 2019 в 05:21
поделиться

У меня были похожие проблемы с 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 / простейшая-форма-конфигурируемой-инъекции-зависимости /

3
ответ дан 7 December 2019 в 05:21
поделиться

Как я понимаю, вы хотите, чтобы конфигурация была глобальной для машины, на которой установлена dll. Существует файл machine.config для опций глобальной конфигурации машины. Я никогда не использовал его сам, поэтому у меня нет более подробной информации, но, возможно, стоит поискать. http://msdn.microsoft.com/en-us/library/ms229697(VS.71).aspx. Поиск в Google по запросу "machine.config" дает больше результатов, которые выглядят информативными.

Другой способ - поместить пользовательский xml-файл в каталог установки dll-файла. Чтобы получить путь к файлу, используйте System.Reflection.Assembly.GetExecutingAssembly.Location (или, возможно, CodeBase вместо Location). К сожалению, вам придется строить собственное управление конфигурацией поверх xml-файла, но благодаря Linq to XML я думаю, что XML стал более безболезненным, чем когда-либо.

0
ответ дан 7 December 2019 в 05:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: