为VB6应用程序暴露C#结构到COM断点 [英] Exposing C# struct to COM breaks for VB6 app

查看:155
本文介绍了为VB6应用程序暴露C#结构到COM断点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最后更新: 2009-08-11下午2:30 EDT



几天前,我发布了这个问题一些很奇怪的问题。好吧,我想出了什么特别是造成一台机器上的构建不运行在别人,甚至想出了一个解决方案,但现在它给我一个很好的,具体的问题:为什么?

$ b $为了重现问题,我创建一个新的InteropUserControl并执行以下操作:


  1. 添加一个新的 public struct MyStruct

  2. 给它一个GUID和 ComVisible 属性

  3. _InteropUserControl 接口添加 GetMyStruct 成员,并在 InteropUserControl

MyStruct p>

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

_InteropUserControl.GetMyStruct()

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

(我已经尝试返回 MyStruct 通过引用传递。)



InteropUserControl.GetMyStruct()实现:

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



我也签署了程序集并将其安装到GAC并注册Regasm。将它添加到一个新的VB6项目并添加对 GetMyStruct()的调用并在我们的构建机器上编译,它拒绝在其他机器上运行。

$ b为了解决这个问题,我不得不暴露一个类到COM而不是结构,基本上改变 GetMyStruct 到这:

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



在我的实际项目中,我在内部检索结构,然后复制所有



因此,为什么一个结构体会导致这个行为和一个类工作精细?有没有一些魔法暴露一个结构到COM在VB6中使用?



我认为它可能与OLE自动化有关。



注意:我也尝试返回结构,而不是使用 ref 参数,但是没有改变行为。



编辑以添加项目模板链接



Interop Forms Toolkit 2.0 是原始的VB.NET项目模板和dll 。我不引用dll,因此您可能不需要安装此文件。



C#CodeProject上的模板的翻译是我用来创建我的项目模板,而不是项目模板。 VB.NET版本自动生成 __ InteropUserControl 事件接口, _InteropUserControl 接口和一些相关属性。

我认为我发现了一个解决方案这个问题。
我有同样的确切问题,vb6打破通过传递结构调用互操作程序库的方法。这是我为测试DLL互操作创建的项目,所以我在我的项目中是一个表单。但我有另一个项目(主应用程序)与相同的引用,它工作正常。



阅读Joel post后,我想测试他的解决方案,工作(使用类而不是结构)。但我有其他interops,我使用结构,所以我很担心,在任何时候,我的应用程序可能会失败。此外,我不想做额外的工作创建和暴露接口和一个类来替换结构。



所以,我从我的形式和移动代码它到模块中的公共子。它立即工作。顺便说一句,这是我在主应用程序中执行的调用是工作正常。



我希望它可以帮助别人。


Last Updated: 2009-08-11 2:30pm EDT

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:

  1. Add a new public struct MyStruct:
  2. Give it a GUID and ComVisible attributes
  3. Add a GetMyStruct member to the _InteropUserControl interface and implement it in InteropUserControl.

MyStruct:

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

_InteropUserControl.GetMyStruct():

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

(I have tried returning MyStruct instead of passing by reference, as well.)

InteropUserControl.GetMyStruct() implementation:

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. 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.

To get around this, I had to expose a class to COM instead of the struct, and basically change GetMyStruct to this:

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?

I think it may have something to do with OLE Automation.

Note: I also tried returning the struct rather than using a ref parameter, but that did not change the behavior.

Edit to add link to project template:

Interop Forms Toolkit 2.0 is the original VB.NET project template and dll. I don't reference the dll, so you may not need to install this.

C# Translations of templates on CodeProject is what I used to create mine (the project template, not the item template). The VB.NET version generates the __InteropUserControl event interface, the _InteropUserControl interface, and a few relevant attributes automagically. Those are explicitly coded in the C# version, and that's about all that's different between the two.

解决方案

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. This is a project I created for testing a DLL interop, so all I have in my project was a form. 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). 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. 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.

这篇关于为VB6应用程序暴露C#结构到COM断点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆