【发布时间】:2011-12-07 02:53:28
【问题描述】:
我需要从 .NET 4.0 应用程序自动执行 Adobe InDesign CS3 中的一些任务。我使用 Visual Studio 中的“添加引用”对话框添加了对 InDesign 类型库的引用。它生成一个互操作程序集,该程序集正确地包括在类型库中声明的所有接口和类型。我没有安装任何 Adobe SDK,因为类型库在 Visual Studio 中可用,除了 Adobe InDesign CS3 之外没有安装任何东西。
现在对我来说互操作程序集中的有趣类型是接口_Application 和Application,以及类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 接口。但是如果我这样做,我会得到一个讨厌的InvalidCastException 说System.__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。
-
我会尝试安装 Adobe SDK,以防 Visual stuido CS3 Api 被搞砸。
-
@HansPassant 我尝试了您的建议来创建
_Application接口的实例,但它在编译时失败,说无法创建抽象类或接口'InDesign._Application '。我认为我可以创建Application的实例(这也是一个接口)的原因是编译器做了一些技巧并实际上实例化了ApplicationClass。我在博客上读到了一些关于此的内容,但不幸的是我现在找不到。 -
当你说你将它投射到(应用程序)接口时,你实际上的意思是你正在将它投射到(InDesign.Application)接口......对吗?
-
@MatsT 是的,没错。 :-) 我明确地将其转换为
InDesign.Application。
标签: c# .net com interop adobe-indesign