C#COM插件系统

时间:2015-04-15 11:29:57

标签: c# plugins visual-studio-2013 com

我目前正处于需要一些建议的地步。在我们公司,我们混合了许多不受管理的语言,如PowerBuilder或纯C ++。现在我们需要.NET中的大量代码。所以我的第一个目的是为什么不只是通过COM创建一个插件系统。

这是我目前正在努力实现的目标。一切正常,插件系统可以加载插件。但是一旦我将我的插件系统暴露给COM并尝试通过加载插件,作为一个例子VBS,我总是得到以下错误:

  

无法加载一个或多个请求的类型。检索LoaderExceptions属性以获取更多信息

根据我的研究,我发现在Assembly.GetTypes()期间无法加载类型时会出现此问题。这真的很奇怪,因为我将我的界面放入它自己的程序集并通过我的插件系统和插件引用它,这样界面总是一样的。

但是当我调试了一点时,我发现实际上问题似乎不是我的界面。当他试图加载继承接口的插件类的类型时,实际发生了加载问题。也许这是界面或其他东西。

但是现在要指出,只要我通过托管代码直接使用插件系统就没有问题。一旦我通过COM这样做,我收到此错误。所以我假设我错过了或搞乱了COM。

目前我真的需要一个解决方案,但不仅仅是解决方案,对解决方案的解释也会非常好,因为我实际上想了解我搞砸了什么。

以下是该解决方案的下载链接。也许你找到了一些东西。

Solution

        [ComVisible(true)]
    public bool Initialize(string dllPlugin)
    {
        try
        {
            string dllPluginPath = Assembly.GetExecutingAssembly().Location.Replace("IncoPluginSystem.dll", "") + "plugins\\";
            string completePluginPath = dllPluginPath + dllPlugin + ".dll";

            if (!File.Exists(completePluginPath))
            {
                pluginError = "The plugin could not be found in the plugins directory.";
                return false;
            }

            plugin = Assembly.LoadFile(completePluginPath);

            if (plugin == null)
            {
                pluginError = "No plugin loaded. Pls initialize first";
                return false;
            }

            foreach (Type t in plugin.GetTypes())
            {
                if (t.GetInterface("IPlugin") != null)
                {
                    pluginInstance = Activator.CreateInstance(t) as IPlugin;
                }
            }

            return true;
        }
        catch (Exception e)
        {
            pluginError = e.Message;
            return false;
        }
    }

问题发生在foreach循环中,你可以访问程序集的类型。

我添加了更详细的异常处理。当我将它暴露给COM

时,这是错误
  

无法加载文件或程序集'IncoPluginSystemInterface,Version-1.0.0.0,Culture = neutral,PuplicKeyToken = 497bca4abf979e3e'或其依赖项之一。系统无法查找指定的文件。   Fusion日志:   警告:装配绑定日志记录已关闭。   注意:程序集绑定失败日志记录会导致性能损失。

DLL的引用只是创建.net库的标准引用。什么都没有补充。

插件系统的结构如下

IncoPluginSystem.dll
IncoPluginSystemInterface.dll
plugins
->IncoPluginSystemInterface.dll
->TestPlugin.dll

所以缺少的dll实际上是需要的2个点。也许是因为IncoPluginSystem.dll作为COM对象加载所以可能路径不正确但我不确定。我测试并改变了我能想象到的一切。所以它肯定是我搞砸COM的东西。

我找到了问题所在。实际上我的DLL确实在错误的位置。只要我将DLL放入GAC就可以了。所以现在我的问题是 - 如何确定将dll丢失的位置。在我的例外中我只看到丢失了什么dll而不是路径。有谁知道如何确定这个?

1 个答案:

答案 0 :(得分:0)

好的我能够自己回答。解释什么是错的。我所做的可以帮助\改善其他人的工作。

我在注册表中打开了FusionLog,在LoaderException上我检查了FusionLog

catch (ReflectionTypeLoadException ex)
        {
            StringBuilder sb = new StringBuilder();
            foreach (Exception exSub in ex.LoaderExceptions)
            {
                sb.AppendLine(exSub.Message);
                FileNotFoundException exFileNotFound = exSub as FileNotFoundException;
                if (exFileNotFound != null)
                {
                    if (!string.IsNullOrEmpty(exFileNotFound.FusionLog))
                    {
                        sb.AppendLine("Fusion Log:");
                        sb.AppendLine(exFileNotFound.FusionLog);
                    }
                }
                sb.AppendLine();
            }
            pluginError = sb.ToString();
        }

在注册表上启用FisonLog后(HKLM \ SOFTWARE \ Microsoft \ Fusion!EnableLog(DWORD 1))我能够看到在执行程序的位置实际需要丢失的DLL OLEObject通过COM创建系统实例。

我没有意识到这一点,但是在某种程度上它是相当逻辑的。幸运的是,我没有弄乱任何关于代码的错误信息。