我需要从 .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
. 据我所知,这是完全正常的。
现在,这里是乐趣的开始。为了让这个实例对我可用,我应该将它转换为正确的接口。从网上的其他示例以及此处可用的文档中,我可以看到我应该将其转换为Application
界面。但如果我这样做,我会得到一个讨厌的InvalidCastException
说法,即该类型System.__ComObject
不支持此接口。如果我尝试将其强制转换ApplicationClass
为_Application
接口,我会得到相同的异常。
我想我可能使用了不正确的接口,所以我尝试实现此处列出的实用程序功能。此函数循环遍历 interop 程序集中声明的所有接口,并查询 IUnknown 接口是否实现了该接口。
当我使用该函数时,它返回 null,这意味着我返回的实例不CreateInstance
支持互操作程序集中的任何接口。肯定是这样吧!?
但是,如果我instance
使用 Visual Studio 调试器检查变量,就会发现有一个叫做“动态视图”的东西。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 更有经验的人知道我可能做错了什么。
在此先感谢,并为这么长的帖子感到抱歉。