请问用.Net写好的DLL如何能让非.Net的程序使用呢?(如VB6)

simanh 2003-08-22 03:14:29
我用.Net写了个Dll,并且已经注册为强名称,在该DLL工程的属性中的"输出"中把COM intep设成了"True",生成的时候输出了DLL文件和对应的.tlb文件

我在VB6中引用该DLL文件,报错,如果引用.tlb文件则成功引用,但是DLL中的函数全看不到,

请问怎么才能让.Net中写的DLL用在VB6中呢?
...全文
61 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
alaisalaix 2003-08-24
  • 打赏
  • 举报
回复
先全注销掉,然后重新注册
GAC里允许多种版本的同一程序集存在,目的是为了避免传统的"dll地狱",但这种方式
也有利有弊


下文转载,作者:builder.com,希望对你有点用处
Windows应用程序经常受到动态链接库的拖累,这就是“DLL地狱”问题,在遇到此类麻烦的时候,应用程序的某一个组件会被其他应用程序的不兼容组件覆盖,结果令受到干扰的应用程序完全不能正确工作。这些问题很难诊断出来,因为它们只有在问题组件安装一段时间之后才会突然冒出来。Visual Basic应用程序的DLL地狱问题更是臭名昭著,因为用Visual Basic语言开发的应用程序相比其他编程语言开发的应用程序具有更大程度的外部相关性。微软推出的.NET计划有望采用一种新型的分布单元assembly(装配)来缓和这一严重问题。


assembly机制初探
从编程的角度来看,一个assembly在功能上等同于Java包:它提供了相关类的可分配库而且定义了它们的范围。对那些不熟悉Java的人来说,在开发应用程序的时候,assembly之于.NET无异于DLL文件之于COM,只不过assembly由多个文件所组成。

Assembly可以通过所谓的名单(manifest)实现自我文档化,这也是它们相比DLL更为优异的一个典型特征。名单包含在assembly之内,由说明assembly的导出类的元数据、这些类所需的外部依附、使用assembly所需的权限以及此类依附的版本控制信息所组成。在.NET框架内,assembly为版本、类以及不能版本化的单个文件提供了公共名称。这样就可以不必检查多个文件以确定系统上安装组件的版本,这也正是我们以往最感到气恼的地方。.NET的这种版本控制特性几乎可以完全消除DLL地狱病。

私有assembly和公共assembly
在缺省的情况下,.NET的assembly是私有的,这意味着它们仅能被某一个应用程序所用。私有的assembly应当被安装到应用程序所在的文件夹或其子文件夹之一。微软希望大多数 .NET开发人员能采用私有的assembly,而事实上它也在鼓励人们这样做。

但是,这样会带来一个潜在的问题:用户的硬盘内可能因为拥有同一私有assembly的多重拷贝而变得混乱不堪,这真是很具有讽刺意味,听起来反倒是COM好象更容易解决这个问题了。微软则是这样回应以上批评的:“硬盘很便宜,买个更大的就行了。”幸好,你可以非常方便地把私有的assembly转为公共assembly,甚至不必重新编译或编辑代码。

共享之美
共享assembly和私有assembly之间的主要差别在于前者通常保存在专门命名的全局装配缓存(简称GAC)内。GAC有时在微软文档中被称为Global Assembly Store,可能是因为后者简称起来好听一些。

GAC能存储同一assembly的多个版本,这就是微软所称的“肩并肩部署”功能。这一功能几乎消除了安装应用程序的不兼容共享组件而影响其他应用程序的可能性,这对开发者来说肯定是个好消息。

客户assembly能指定它兼容哪个或者那些共享assembly的版本。如果客户程序的版本要求不能被满足,那么.NET运行时就不会装载任何服务器assembly。顺便说一句,.NET的assembly版本由4位数字格式表示,形式如:主版本号.次版本号.创建版本号.修订版本号。

默认地。一个assembly被认为只能兼容具有同样主版本和次版本号的共享assembly。然而运行时装载器却优先装载相比客户版本具有更高创建版本号或者修订版本号的assembly,如果存在这样的assembly,就会自动地为其提供修补支持。这种缺省行为并不一定总是你所希望的,因此程序员或系统管理员可以定义定制的版本控制策略,比方说,强迫装载某一特定的版本或者禁用装载器对更高创建版本号或者修订版本号的assembly的装载。

在Beta 1版上,版本控制策略包含在一些XML文件内,而这些文件则要不驻留在应用程序目录下要不就保存在Windows目录下。这些XML文件分别定义了同特定软件相关的版本策略以及系统范围内的版本控制策略。

命名

你可以随意命名私有的assembly,只要其名称在应用程序内唯一即可。另一方面,公共assembly则需要采用某种全局唯一标识符以便.NET运行时可以识别它们。COM的Class ID和Prog ID已经随风而逝了。现在的共享assembly采用了所谓的strong name命名机制。Strong name来源于标准的公钥加密算法。开发人员用一个私钥“签署”assembly同时提供一个公钥供客户assembly使用。公钥随后成为assembly的strong name的一部分。


采用命令行编译器签署assembly需要使用一些命令行指令选项,因此这也是一项比较繁重的任务。幸好,Visual Studio.NET可以自动地为程序员完成这些工作。

小小装配做大事
微软最后还是承认了DLL地狱问题的存在,而且意识到这一问题只能通过操作系统级施加控制策略才能得以弥补。在注册表和对COM应用程序单个组件支持这方面瞎折腾一气之后,看起来好象微软已经走上了正途。事实上,有了assembly机制,安装.NET应用程序完全可能变成使用Xcopy命令拷贝程序那么简单!



simanh 2003-08-23
  • 打赏
  • 举报
回复
回楼上的,我在VB中引用该DLL时,如果直接引用DLL文件,则报错“不能将引用加入到指定文件”
如指向该DLL的tlb,则可以加引用,但是在对象浏览器中虽然可以看到DLL中的类,但是看不到该类的任何成员,请问是什么回事呢?而.net则一切正常
simanh 2003-08-23
  • 打赏
  • 举报
回复
ok了,我注册为GAC后就可以了
但是我多次注册同个assembly,造成OLE/COM浏览器看到多个同名assembly,但是只有一个有用,请问怎么消除那些无用的已注册的assembly呢?
simanh 2003-08-23
  • 打赏
  • 举报
回复
先谢谢楼上的,回楼上,不行
完全按照您的例子做了一次,报错“424,要求对象”

什么回事??请问你的例子需要注册为GAC吗?
alaisalaix 2003-08-23
  • 打赏
  • 举报
回复
>>>我用.Net写了个Dll,并且已经注册为强名称,在该DLL工程的属性中的"输出"中把
>>>COM intep设成了"True",生成的时候输出了DLL文件和对应的.tlb文件

这一步是正确的,只要你用的是.net环境,按照上面的过程,就已经创建了ccw。
无需做tlbexp,gacutil或regasm之类的过程,.net已经自动完成了创建供非托管环境
使用的托管代码的代理,即ccw
问题可能出在vb中引用该dll。很简单,只要通过工程->添加引用,把ccw(一个dll文件,
文件名取决于你在.net工程属性中的设置),然后就可以在vb中使用这个dll中的方法了
你的报错会不会是vb中使用时出了问题??
alaisalaix 2003-08-23
  • 打赏
  • 举报
回复
我试了一下,对象浏览器里确实是如你所说看不到类的任何成员,
但没关系,你仍可以使用该类提供的公共属性和方法
我测试的一个例子很简单,如下:
1。在.net中创建一个类库,Test.cs文件内容如下:
using System;
namespace Test
{
/// <summary>
/// Class1 的摘要说明。
/// </summary>
public class MyClass
{
public MyClass()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
public string hello()
{
return "hello,world";
}
}
}
注:工程的属性->配置->生成->注册为COM interop设置为true,编译该工程即可,自动生成并
注册了myClass类和Test类型库,可以通过OLE/COM Object Viewer查看,或到注册表查看
2。建立一个vb6工程,在工程->引用...中找到test,把复选框钩上,然后在对象浏览器中
可看到这个test下的类(我也不太清楚为什么看不到类的方法),在窗体上放上一个button
和一个label,在button的点击事件中加入如下代码:

Dim myClass1 As New myClass
Label1.Caption = myClass1.hello()

运行后,点击button,label1显示为“hello,world”,一切正常,可以试一试
Stevetan81 2003-08-22
  • 打赏
  • 举报
回复
dll是非托管代码吗?
jlhdlj 2003-08-22
  • 打赏
  • 举报
回复
看一下.net framework sdk中的"向 COM 公开 .NET Framework 组件"一节
s5689412 2003-08-22
  • 打赏
  • 举报
回复
这个问题一句两句也说不大清楚,我最近对这个问题也比较感兴趣,建议看看下面这篇文章以及文章所提供的一些资料链接,会有帮助的。

Understanding Classic COM Interoperability With .NET Applications
http://www.codeproject.com/dotnet/cominterop.asp
simanh 2003-08-22
  • 打赏
  • 举报
回复
回楼上的,已经gacutil了
fq_ln 2003-08-22
  • 打赏
  • 举报
回复
安装和注册程序集
为了从非托管代码真正创建托管类型,需要在全局程序集缓存 (GAC) 中安装该程序集,并将其注册以便从 COM 使用。
可使用 gacutil.exe 实用工具在全局程序集缓存中安装程序集。可使用 /u 选项来卸载程序集。

gacutil /i TestServer.dll

如果程序集要由单个应用程序专用,则可将其直接复制到该应用程序目录中(而不是将该程序集安装在 GAC 中)。专用程序集不需要共享名称,但是必须将其注册以便从 COM 使用。
可使用 regasm.exe 实用工具来注册程序集。可使用 /u 选项来卸载程序集。

regasm TestServer.dll


编写和编译非托管代码
程序集一旦完成注册并正确安装后,就可从 COM 使用程序集中定义的类型,就像使用正常的 COM 类型一样。例如,可通过调用 CoCreateInstance API,或者通过从 Visual Basic 或脚本语言调用 CreateObject 或 GetObject 来创建新对象。
lyrixliu 2003-08-22
  • 打赏
  • 举报
回复
通过使用TLBEXP.exe导出后的vb可以使用
"Tlbexp.exe generates a type library that contains definitions of the types defined in the assembly. Applications such as Visual Basic 6.0 can use the generated type library to bind to the .NET types defined in the assembly."

See MSDN LIB:
.NET Framework Tools

Type Library Exporter (Tlbexp.exe)
csharplove 2003-08-22
  • 打赏
  • 举报
回复
通过RCW可以使用COM组件和.NET客户,通过他非托管COM客户可以使用.NET组件
为了让COM客户引用.NET组件,需要为组件生成COM可调用的包装器CCW。作为.NET组件的代理

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧