COM返回一个没有实现任何接口类型接口类型、COM

2023-09-05 01:22:29 作者:愛哭的毛毛蟲

我需要从一个.NET 4.0应用程序自动在Adobe InDesign CS3的一些任务。我添加使用Visual Studio中的添加引用对话框中引用的InDesign类型库。它genereates互操作程序集,其中正确包括所有类型库中声明的接口和类型。我还没有安装任何Adobe的SDK,因为类型库是在Visual Studio中提供,而无需安装任何东西,但Adobe公司的InDesign CS3。

I need to automate some tasks in Adobe InDesign CS3 from a .NET 4.0 application. I've added a reference to the InDesign Type Library using the Add Reference dialog in Visual Studio. It genereates an interop assembly, which correctly includes all of the interfaces and types declared in the type library. I haven't installed any Adobe SDK, as the type library was available in Visual Studio without installing anything but Adobe InDesign CS3.

有趣的类型的互操作程序集,我现在是在接口 _Application 应用程序,类 ApplicationClass 。这里是他们的定义,所以你可以看到它们之间的关系:

The interesting types in the interop assembly for me right now is the interfaces _Application and Application, and the class ApplicationClass. Here is the definition of them, so you can see the relationship between them:

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对象是这样的:

I try to instantiate the COM object like this:

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

这code成功。我得到一个实例,但一个名为类型的 __ ComObject 。据我所知,这是完全正常的。

This code succeeds. I get an instance, but of a type called __ComObject. From what I know, this is completely normal.

现在,这里是有趣的开始。对于这种情况下是可用的给我,我应该将其转换成正确的接口。从网络上的其他例子,并从可用的文档这里,我可以看到我应该将其转换成应用程序接口。但是,如果我这样做,我得到一个讨厌的 InvalidCastException的说,键入系统.__ ComObject 不支持此接口。如果我尝试将其转换为我得到了同样的异常 ApplicationClass _Application 接口。

Now, here's where the fun begins. For this instance to be usable to me, I should cast it to the correct interface. From other examples on the net, and from the documentation available here, I can see I should cast it to the Application interface. But if I do that, I get a nasty InvalidCastException saying that the type System.__ComObject doesn't support this interface. I get the same exception if I try to cast it to ApplicationClass or the _Application interface.

我想我也许是使用了不正确的接口,所以我想实现的效用函数此处上市。这个函数遍历所有的interop程序中声明的接口和查询IUnknown接口,如果它实现了接口。

I thought I was perhaps using an incorrect interface, so I tried implementing the utility function listed here. This function loops through all the interfaces declared in the interop assembly and queries the IUnknown interface if it implements the interface.

当我使用这个函数,它返回null,这意味着该实例我回到从的CreateInstance 支持的在互操作的接口没有的部件。当然,这不可能是正确的!?

When I use that function, it returns null, meaning that the instance I get back from CreateInstance supports none of the interfaces in the interop assembly. Surely, that can't be right!?

不过,如果我检查实例与Visual Studio调试变量,有一种叫动态视图。如果我展开,它会列出所有属性的对象和所有属性相匹配的 ApplicationClass 类和 _Application 接口。所以我试图用 Type.InvokeMember 和作品:

However, if I inspect the instance variable with the Visual Studio Debugger, there's something called "Dynamic View". If I expand that, it lists all the properties for the object and all the properties match the properties from the ApplicationClass class and the _Application interface. So I tried using Type.InvokeMember and that works:

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

这实际工作,但它是非常繁琐的像这样的COM对象进行交互,而我需要做的COM对象的互动很多,所以这是不是真的有用。我想我可以做一个包装的COM对象,但那种失败的interop程序集的目的,我不希望创建700包装类。

This actually works, but it would be extremely cumbersome to interact with the COM object like this, and I need to do alot of interaction with the COM object, so this is not really usable. I guess I could make a wrapper for the COM objects, but that kind of defeats the purpose of the interop assembly, and I don't want to create 700+ wrapper classes.

我搜索了很多,我发现教程和使用的InDesign COM对象的例子,但他们都只是投实例返回给应用程序接口,但作为解释,这并不在我的情况下工作。

I've searched alot, and I've found tutorials and examples of using the InDesign COM object, but they all just cast the instance returned to the Application interface, but as explained, this doesn't work in my case.

我也试过以下code,而不是code以上:

I've also tried the following code instead of the code above:

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

第一行成功,我得到 ApplicationClass 的实例,但是,当它试图执行第二行我得到一个InvalidCastException的说明 ApplicationClass 不能转换到接口 _Application

The first line succeeds and I get an instance of ApplicationClass, but when it tries to execute the second line I get a InvalidCastException stating that ApplicationClass cannot be converted to the interface _Application.

我真的走投无路了这里,而不是一定要尝试像。我真的希望有人比较熟悉COM和NET有什么我可以做错误的想法。

I'm really cornered up here, and not sure what to try next. I really hope someone more experienced with COM and .NET has an idea of what I could be doing wrong.

在此先感谢和抱歉这么长的帖子。

Thanks in advance, and sorry for such a long post.

推荐答案

您必须使用的运行时可调用包装

您所需要的方法是这个

试试这个:

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