简体   繁体   English

ComVisible .NET程序集和app.config

[英]ComVisible .NET assembly and app.config

  • I have .NET assembly with some classes marked as ComVisible 我有.NET程序集,其中一些类标记为ComVisible
  • This assembly is registered with regasm /codebase "assembly_path" 此程序集使用regasm /codebase "assembly_path"
  • I have app.config name (actually - MyAssemblyName.dll.config ) which are in assembly's folder 我有app.config名称(实际上是MyAssemblyName.dll.config ),它们位于程序集的文件夹中
  • I access to appSettings in my assembly through ConfigurationManager.AppSettings["SettingName"] 我通过ConfigurationManager.AppSettings["SettingName"]访问我的程序ConfigurationManager.AppSettings["SettingName"] appSettings
  • I have VBScript file which creates my COM object through CreateObject("...") 我有VBScript文件,它通过CreateObject("...")创建我的COM对象
  • When object is created (from VBScript), ConfigurationManager.AppSettings["SettingName"] returns null. 创建对象时(来自VBScript), ConfigurationManager.AppSettings["SettingName"]返回null。 It looks like assembly doesn't see config file. 它看起来像程序集没有看到配置文件。

What should I to do to make it workable? 我应该怎么做才能使它可行?

One possible way, as Komyg said, is to read config file directly, instead of using ConfigurationManager's embedded behavior. 正如Komyg所说,一种可能的方法是直接读取配置文件,而不是使用ConfigurationManager的嵌入行为。 For those, who will have the same problem: instead of 对于那些会遇到同样问题的人:而不是

ConfigurationManager.AppSettings["SettingName"]

you can use: 您可以使用:

var _setting = ConfigurationManager.AppSettings["SettingName"];
// If we didn't find setting, try to load it from current dll's config file
if (string.IsNullOrEmpty(_setting))
{
    var filename = Assembly.GetExecutingAssembly().Location;
    var configuration = ConfigurationManager.OpenExeConfiguration(filename);
    if (configuration != null)
        _setting = configuration.AppSettings.Settings["SettingName"].Value;
}

This way you will always use read settings from file YourAssemblyName.dll.config which lays in your assembly's folder. 这样,您将始终使用文件YourAssemblyName.dll.config读取设置,该文件位于程序集的文件夹中。 It will allow you to use also another features for app.config (like appSetting 's file attribute), which will no be available if you will use XPath or something like this. 它将允许您使用app.config另一个功能(如appSettingfile属性),如果您将使用XPath或类似的东西将无法使用。

I had the same problem. 我有同样的问题。 An explorer shell extension (Com visible, registered via regasm /codebase) which required an app.config file, could not find nor the connection strings neither the settings. 需要app.config文件的资源管理器外壳扩展(Com可见,通过regasm / codebase注册)无法找到连接字符串,也无法找到设置。

What I did: 我做了什么:

string assemblyLoc          = GetType().Assembly.Location;
string configName           = assemblyLoc + ".config";
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", configName);

That assumes, that the config file is stored in the same directory as the assembly. 这假设配置文件存储在与程序集相同的目录中。

I used sputnik's answer, worked great in one IIS test environment, but not another. 我使用了sputnik的答案,在一个IIS测试环境中工作得很好,但不是另一个。 It turns out that after you set APP_CONFIG_FILE property, you may need to use reflection to touch the ConfigurationManager class to make the change stick. 事实证明,在设置APP_CONFIG_FILE属性后,您可能需要使用反射来触摸ConfigurationManager类以使更改成为可能。 I used this function after setting the APP_CONFIG_FILE property: 我在设置APP_CONFIG_FILE属性后使用了这个函数:

    private static void ResetConfiguration()
    {
        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);
    }

Beyond this, it's probably a good idea to first save off the property and then restore it when you are done: 除此之外,首先保存财产然后在完成后恢复它可能是个好主意:

string oldConfigName = AppDomain.CurrentDomain.GetData("APP_CONFIG_FILE").ToString();
        //do custom stuff in here
        AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", oldConfigName); //re-point to the original configuration.
        ResetConfiguration();

Is everything on the same folder (your dll, vb script, config file, etc)? 一切都在同一个文件夹(你的DLL,vb脚本,配置文件等)? If not, you could try to add the full path to the config file in the PATH evironment variable... 如果没有,您可以尝试在PATH环境变量中添加配置文件的完整路径...

Also if you are running this VB Script inside Internet Explorer you might have some security issues (normally the IE doesn't allow you access to the hard drive). 此外,如果您在Internet Explorer中运行此VB脚本,则可能存在一些安全问题(通常IE不允许您访问硬盘驱动器)。 In this case you can try to put the config file in your desktop, I don't know why but that seems to be the default path when it runs an ActiveX program, so it might also be true for an VB Script. 在这种情况下,您可以尝试将配置文件放在桌面上,我不知道为什么,但它似乎是运行ActiveX程序时的默认路径,因此对于VB脚本也可能如此。

Finally you could add some debugging to your dll, something like creating a simple text file and looking for it afterwards, this way you can see where does your system is actually running your library. 最后,您可以为您的dll添加一些调试,例如创建一个简单的文本文件并在之后查找它,这样您就可以看到您的系统实际运行库的位置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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