【问题标题】:COM returns type that does not implement any interfaceCOM 返回不实现任何接口的类型
【发布时间】:2011-12-07 02:53:28
【问题描述】:

我需要从 .NET 4.0 应用程序自动执行 Adob​​e InDesign CS3 中的一些任务。我使用 Visual Studio 中的“添加引用”对话框添加了对 InDesign 类型库的引用。它生成一个互操作程序集,该程序集正确地包括在类型库中声明的所有接口和类型。我没有安装任何 Adob​​e SDK,因为类型库在 Visual Studio 中可用,除了 Adob​​e InDesign CS3 之外没有安装任何东西。

现在对我来说互操作程序集中的有趣类型是接口_ApplicationApplication,以及类ApplicationClass。这是它们的定义,所以你可以看到它们之间的关系:

public interface _Application
{
    // Lots of properties and methods
}

public interface Application : _Application
{
    // Empty
}

public class ApplicationClass : _Application, Application
{
    // The same properties and methods as declared in _Application
}

我尝试像这样实例化 COM 对象:

Type oType = Type.GetTypeFromProgID("InDesign.Application.CS3");
if (oType != null)
{
    object instance = Activator.CreateInstance(oType);
}

此代码成功。我得到了一个实例,但类型为__ComObject。据我所知,这是完全正常的。

现在,乐趣从这里开始。为了让这个实例对我可用,我应该将它转换为正确的接口。从网上的其他示例和documentation available here 中,我可以看到我应该将其转换为Application 接口。但是如果我这样做,我会得到一个讨厌的InvalidCastExceptionSystem.__ComObject 类型不支持这个接口。如果我尝试将其强制转换为 ApplicationClass_Application 接口,我会得到同样的异常。

我想我可能使用了不正确的接口,所以我尝试实现实用函数listed here。该函数循环遍历 interop 程序集中声明的所有接口,并查询 IUnknown 接口是否实现了该接口。

当我使用该函数时,它返回 null,这意味着我从 CreateInstance 返回的实例支持互操作程序集中的接口none。肯定是这样吧!?

但是,如果我使用 Visual Studio 调试器检查 instance 变量,就会发现有一个叫做“动态视图”的东西。如果我展开它,它会列出对象的所有属性,并且所有属性都与ApplicationClass 类和_Application 接口中的属性相匹配。所以我尝试使用Type.InvokeMember 并且有效:

oType.InvokeMember("DoScript", BindingFlags.InvokeMethod, null, instance, oArguments, CultureInfo.InvariantCulture);

这确实可行,但是像这样与 COM 对象交互会非常麻烦,而且我需要与 COM 对象进行大量交互,所以这并不是真正可用的。我想我可以为 COM 对象制作一个包装器,但这违背了互操作程序集的目的,我不想创建 700 多个包装器类。

我搜索了很多,找到了使用 InDesign COM 对象的教程和示例,但它们都只是将实例转换为返回到应用程序接口,但正如解释的那样,这在我的情况下不起作用。

我也尝试了以下代码而不是上面的代码:

InDesign.Application app = new InDesign.Application();
app.Activate();

第一行成功,我得到了一个ApplicationClass 的实例,但是当它尝试执行第二行时,我得到一个 InvalidCastException,指出 ApplicationClass 无法转换为接口 _Application

我真的被困在这里,不知道下一步该尝试什么。我真的希望对 COM 和 .NET 更有经验的人知道我可能做错了什么。

提前致谢,很抱歉发了这么长的帖子。

【问题讨论】:

  • C# 4.0 dynamic 关键字旨在使第一个代码更易于编写。或者使用 VB.NET。尝试在第二个 sn-p 中使用 _Application 而不是 Application。
  • 我会尝试安装 Adob​​e SDK,以防 Visual stuido CS3 Api 被搞砸。
  • @HansPassant 我尝试了您的建议来创建_Application 接口的实例,但它在编译时失败,说无法创建抽象类或接口'InDesign._Application '。我认为我可以创建Application 的实例(这也是一个接口)的原因是编译器做了一些技巧并实际上实例化了ApplicationClass。我在博客上读到了一些关于此的内容,但不幸的是我现在找不到。
  • 当你说你将它投射到(应用程序)接口时,你实际上的意思是你正在将它投射到(InDesign.Application)接口......对吗?
  • @MatsT 是的,没错。 :-) 我明确地将其转换为InDesign.Application

标签: c# .net com interop adobe-indesign


【解决方案1】:

你必须使用Runtime Callable Wrapper

你需要的方法是this one

试试这个:

    Type oType = Type.GetTypeFromProgID("InDesign.Application.CS3");
    if (oType != null)
    {
        object instance = Activator.CreateInstance(oType);// or any other way you can get it
        Application app = 
            (Application)System.Runtime.InteropServices.Marshal.CreateWrapperOfType(instance, typeof(ApplicationClass));
    }

【讨论】:

  • 哇!你是绝对正确的!这样可行!太感谢了! :-D 我认为互操作程序集 Runtime Callable Wrapper。我一定会阅读您提供的链接。再次感谢!
  • 但是 RCW 上的属性和方法返回__ComObject。它们是自动包装的,还是在从方法调用中接收它们时我需要做一些特殊的技巧?
  • 我不确定,但据我所知,Application 方法和属性应该返回互操作中定义的接口。如果没有,您将不得不包装所有内容。请告诉我:-)
  • 只是快速跟进。所有返回的对象都被正确包装,所以我只需要包装Application 实例。但有些方法返回 object 类型,我必须将其转换为正确的类型。但这也没有任何问题。所以一切都很好。再次感谢您的帮助,非常感谢! :-)
  • 我必须将 InDesign 类型库引用的属性“嵌入互操作类型”设置为 false。
【解决方案2】:

@Seb 解决方案是正确的,但在处理它时,我遇到了错误“源对象无法转换为目标类型,因为它不支持所有必需的接口。” (正如@MikeKeskinov 在 cmets 中所写的那样)。

要消除该错误,您需要通过执行这些步骤来注册 COM 对象(已解释 here) - 这适用于 InDesign CC2021 v16.0(其他版本类似)

  • 使用任务管理器关闭所有 InDesign 实例
  • 转到 C:\ProgramData\Adobe\InDesign\Version 16.0\en_US\Scripting Support\16.0 并将 tlb 文件重命名为 tlb.bak(或类似的,没关系)
  • 以管理员身份打开命令窗口 (CMD)
  • 转到 InDesign EXE 文件夹C:\Program Files\Adobe\Adobe InDesign 2021
  • 启动命令indesign.exe -type
  • 将新创建的 tlb 文件引用到项目中

然后它应该工作。希望我对某人有所帮助!

【讨论】:

    【解决方案3】:

    我最近没有使用 COM,但据我记得(并且理解你的问题)你不能像这样转换 ComObject:

       Application app = (Application)comObject;
    

    但你应该使用 as 运算符:

        Application = comObject as Application;
    

    【讨论】:

    • 动态转换的结果是null,因为__ComObject 与.net 模型中的Application 无关。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-22
    • 1970-01-01
    • 2012-10-06
    • 2011-05-16
    • 1970-01-01
    • 2011-06-22
    • 2011-08-23
    相关资源
    最近更新 更多