简体   繁体   English

对于VB6应用程序,将C#struct暴露给COM中断

[英]Exposing C# struct to COM breaks for VB6 app

Last Updated: 2009-08-11 2:30pm EDT 最后更新时间: 2009-08-11美国东部时间下午2:30

A few days ago I posted this question about some very strange problems. 前几天我张贴了这个问题的一些很奇怪的问题。 Well, I figured out what specifically was causing a build on one machine to not run on others and even came up with a work-around, but now it leaves me with a nice, specific question: Why? 好吧,我弄清楚是什么原因导致一台机器上的构建不能在其他机器上运行甚至想出一个解决方案,但现在它给我留下了一个很好的,具体的问题:为什么?

To reproduce the problem, I create a new InteropUserControl and do the following: 为了重现这个问题,我创建了一个新的InteropUserControl并执行以下操作:

  1. Add a new public struct MyStruct : 添加一个新的public struct MyStruct
  2. Give it a GUID and ComVisible attributes 给它一个GUID和ComVisible属性
  3. Add a GetMyStruct member to the _InteropUserControl interface and implement it in InteropUserControl . GetMyStruct成员添加到_InteropUserControl接口并在InteropUserControl实现它。

MyStruct : MyStruct

[Guid("49E803EC-BED9-4a08-B42B-E0499864A169")]
[ComVisible(true)]
public struct MyStruct {
    public int mynumber;
}

_InteropUserControl.GetMyStruct() : _InteropUserControl.GetMyStruct()

[DispId(7)]
void getMyStruct( int num, ref MyStruct data );

(I have tried returning MyStruct instead of passing by reference, as well.) (我已经尝试返回MyStruct而不是通过引用传递。)

InteropUserControl.GetMyStruct() implementation: InteropUserControl.GetMyStruct()实现:

public void getMyStruct( int num, ref MyStruct data ) {
    data = new MyStruct();
    data.mynumber = num * 2;
}

I also sign the assembly and install it to the GAC and register with Regasm. 我还签署了程序集并将其安装到GAC并注册Regasm。 Upon adding it to a new VB6 project and adding a call to GetMyStruct() and compiling on our build machine, it refuses to run on other machines. 将它添加到新的VB6项目并添加对GetMyStruct()的调用并在我们的构建机器上进行编译后,它拒绝在其他机器上运行。

To get around this, I had to expose a class to COM instead of the struct, and basically change GetMyStruct to this: 为了解决这个问题,我不得不将一个类暴露给COM而不是结构,并且基本上将GetMyStruct更改为:

public void GetMyData( int num, MyClass data ) {
    data.mynumber = num * 2;
}

In my actual project, I retrieve the struct internally, and then copy all the field values from the struct to the matching members on the instance of the class passed to the method by the client. 在我的实际项目中,我在内部检索结构,然后将结构中的所有字段值复制到客户端传递给方法的类的实例上的匹配成员。

So why did a struct cause this behavior and a class worked fine? 那么为什么一个结构导致这种行为并且一个类工作正常呢? Is there some magic to exposing a struct to COM for using in VB6? 将结构暴露给COM以便在VB6中使用是否有一些魔力?

I think it may have something to do with OLE Automation. 我认为它可能与OLE自动化有关。

Note: I also tried returning the struct rather than using a ref parameter, but that did not change the behavior. 注意:我也尝试返回结构而不是使用ref参数,但这并没有改变行为。

Edit to add link to project template: 编辑以添加项目模板的链接:

Interop Forms Toolkit 2.0 is the original VB.NET project template and dll. Interop Forms Toolkit 2.0是原始的VB.NET项目模板和dll。 I don't reference the dll, so you may not need to install this. 我没有引用dll,所以你可能不需要安装它。

C# Translations of templates on CodeProject is what I used to create mine (the project template, not the item template). C#CodeProject上的模板翻译是我用来创建我的模板(项目模板,而不是项目模板)。 The VB.NET version generates the __InteropUserControl event interface, the _InteropUserControl interface, and a few relevant attributes automagically. VB.NET版本自动生成__InteropUserControl事件接口, _InteropUserControl接口和一些相关属性。 Those are explicitly coded in the C# version, and that's about all that's different between the two. 这些是在C#版本中明确编码的,这就是两者之间的所有不同之处。

I think I found a solution to this problem. 我想我找到了解决这个问题的方法。 I had the same exact problem, vb6 breaks when calling a method of an interop library by passing an structure. 我有同样的问题,vb6在通过传递结构调用互操作库的方法时中断。 This is a project I created for testing a DLL interop, so all I have in my project was a form. 这是我为测试DLL互操作而创建的项目,因此我在项目中拥有的只是一个表单。 But I had another project (the main application) with the same reference and it works fine. 但我有另一个项目(主要应用程序)与相同的参考,它工作正常。

After reading Joel post, I wanted to test his solution and in fact id did work (using a class instead a structure). 在阅读Joel帖子后,我想测试他的解决方案,实际上id确实有效(使用类而不是结构)。 But I have other interops where I'm using structures, so I was quite worried that at any point my application might fail. 但我还有其他使用结构的互操作,所以我很担心在任何时候我的应用程序都可能失败。 Additionally I didn't want to do the extra work of creating and exposing interface and a class to replace the structure. 另外,我不想做额外的工作来创建和公开接口和一个类来替换结构。

So, I took the code from my form and move it to a public sub in a module. 所以,我从我的表单中获取代码并将其移动到模块中的public sub。 It Worked immediately. 它立即工作。 By the way, that's how i had implemented the call in the main application which was working ok. 顺便说一句,这就是我在主应用程序中实现调用的方式。

I hope it might help others. 我希望它可以帮助别人。

Is there some magic to exposing a struct to COM for using in VB6? 将结构暴露给COM以便在VB6中使用是否有一些魔力?

The article COM Data Types * on MSDN says that structs are supported. 文章COM数据类型 * MSDN上说,结构支持。 Specifically, the MSDN article says that COM structures are defined as: 具体来说,MSDN文章说COM结构定义为:

ByRef VALUETYPE< MyStruct >

There are also a couple of articles on customing your COM-callable wrappers at the bottom of the page, you may wish to review those. 在页面底部还有一些关于自定义COM可调用包装器的文章,您可能希望查看这些文章。

  • Edit (2016): Original link was broken, so I fixed it to Version 3.5 of the .Net Framework. 编辑(2016):原始链接已损坏,因此我将其修复为.Net Framework的3.5版。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM