COM返回未实现任何接口的类型

我需要从.NET 4.0应用程序中自动执行Adobe InDesign CS3中的某些任务。 我使用Visual Studio中的“添加引用”对话框添加了对InDesign类型库的引用。 它创建了一个interop程序集,它正确地包含了类型库中声明的所有接口和类型。 我没有安装任何Adobe SDK,因为Visual Studio中提供的类型库没有安装除Adobe InDesign CS3之外的任何东西。

对我来说,interop程序集中有趣的类型是接口_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的类型。 据我所知,这是完全正常的。

现在,这里是有趣的开始。 为了让这个实例可以使用,我应该将它转换为正确的接口。 从网上的其他示例和此处提供的文档中 ,我可以看到我应该将它转换为Application接口。 但是如果我这样做,我会得到一个令人讨厌的InvalidCastExceptionSystem.__ComObject类型不支持这个接口。 如果我尝试将其转换为ApplicationClass_Application接口,我会得到相同的exception。

我以为我可能使用了错误的界面,所以我尝试实现此处列出的实用程序function。 此函数循环遍历interop程序集中声明的所有接口,并在IUnknown接口实现接口时查询它。

当我使用该函数时,它返回null,这意味着我从CreateInstance返回的实例不支持interop程序集中的任何接口。 当然,这不可能是对的!?

但是,如果我使用Visual Studio Debugger检查instance变量,则会出现名为“Dynamic View”的内容。 如果我展开它,它会列出对象的所有属性,所有属性都与ApplicationClass类和_Application接口的属性相匹配。 所以我尝试使用Type.InvokeMember ,它的工作原理如下:

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

这实际上是有效的,但是像这样与COM对象进行交互会非常麻烦,而且我需要与COM对象进行很多交互,所以这不是真的可用。 我想我可以为COM对象创建一个包装器,但这种方法违背了互操作程序集的目的,而且我不想创建700多个包装器类。

我搜索了很多,并且我找到了使用InDesign COM对象的教程和示例,但是他们都只是将实例转换为Application接口,但正如所解释的,这在我的情况下不起作用。

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

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

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

我真的在这里走投无路,不知道下一步该尝试什么。 我真的希望有更多经验的COM和.NET能够了解我可能做错了什么。

在此先感谢,并为这么长的post感到抱歉。

您必须使用Runtime Callable Wrapper

你需要的方法就是这个

试试这个 :

  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)); } 

我最近没有使用COM,但到目前为止我记得(并理解你的问题)你不能像这样强制转换ComObject:

  Application app = (Application)comObject; 

但你应该使用as运算符:

  Application = comObject as Application;