请教如何用vb生成非ActiveX的dll

时间:2022-12-19 21:05:12
vb的界面好像没有这样的功能,但之前听说有方法可以实现,请问具体如何实现

6 个解决方案

#1


'VB作为一种简单容易上手的语言,可以让开发者快速上手,开发速度快,效率高。但它过分的封装也给开发者带来诸多不便。 

'问题的由来 

'最近本人在开发一个插件结构的项目中就遇到了一个麻烦,我的项目是采用COM架构, 
'框架由DELPHI开发,插件为COM组件,插件可以由其他语言开发,当然也包括VB。 
'每个插件必须注册为一个固定的组件类别(Categories)。 
'在其他语言如VC、DELPHI中实现起来非常简单,只需要重载DllRegisterServer、DllUnregisterServer 
'在两个函数里加入注册注销类别的代码,然后输出就可以了。但到了VB就碰到麻烦了。 

'VB正常情况下是不能直接开发标准DLL,所以也就不支持自定义导出函数, 
'开发ACTIVE DLL的时候,是由VB自动导出必须的四个函数 
'DllGetClassObject,DllCanUnloadNow, DllRegisterServer, DllUnregisterServer。 
'要加入注册注销类别代码就必须重新导出DllRegisterServer, DllUnregisterServer。 

'好了,问题就转换成了如何在VB写的DLL中导出函数了 

'VB编译内幕 
'VB的编译过程大致如下,当我们在编辑环境中编写完代码后,VB调用C2将所有的模块(包括CLASS) 
'编译成OBJ文件(能够为机器语言识别的代码)。一下是C2的一些编译参数说明(E文): 

'- the the name of the prefixed one used for the names of the rowscontaining '' precompilato'', 
'one risen of intermediate tails (from which name of the switch) temporary; 
'these rows are 5 and finish withi suffissi GL, SY, FORMER, IN and DB; they contained are not documented 

'- f the name of the rows to compile 

'- W3 warning level 3, level of '' attenzione'' dedicating to i warnings 

'- Gy it qualifies the connection to level of function (function-level linking) 

'- G5 optimization for the Pentium 

'- Gs4096 it allows not to insert the code for the control of stack (stack probe) if a function does not 

'use more than 4096 byte of stack 

'- dos not documented 

'- Z1 it removes the name of the bookcase of default from the rows.OBJ 

'- Fofileobj the name of rows OBJ to generate (rows output) 

'- Qifdiv it puts in action the corrections for the bug of the division of the Pentium (FDIV bug) 

'- MILILITER it creates rows eseguibile single-threaded 

'- basic it indicates the compiler C2 the fact that the compilation it happens for a plan basic 


'C2完成编译后,VB会调用LINK.EXE将所有的OBJ文件连接成EXE文件,完成编译过程。 
'下面是一段命令行演示如何调用LINK.EXE: 

'LINK C:\Test\Form1.obj C:\Test\Modulo1.obj C:\Test\Progetto1.obj C:\Programmi\Microsoft Visual Studio\VB98\VBAEXE6.lib /ENTRY:__ vbaS /OUT:C:\Test\Progetto1.exe /BASE:0x400000 /SUBSYSTEM:WINDOWS, 4.0 /VERSION:1.0 /DEBUG /DEBUGTYPE:CV /INCREMENTAL:NOT /OPT:REF/MERGE:.rdata =.text /IGNORE:4078 
'对于我们来说这些参数没有什么意义,用默认的就行了。这段命令行中并没有包括输出函数, 
'如果我们希望输出函数,可以定义一个.def文件,按照格式加入要输出的函数列表, 
'然后在命令行后面加上 “/DEF: 文件名”(当然也可以直接加/ EXPORTS参数), 
'再调用命令行编译,用的denpendency工具查看你就会发现你要输出的函数了。 

'Def文件格式的定义: 
'LIBRARY 程序名称 
'Description "MyDLL - (C) Antonio Giuliana, 2004" 
'EXPORTS 
'函数名= ?函数名@函数所在模块名@@AAGXXZ 
'… 

'例: 

'LIBRARY MyDLL 
'Description "MyDLL - (C) Antonio Giuliana, 2004" 
'EXPORTS 
'DllRegisterServer= ?DllRegisterServer@SymExp@@AAGXXZ 
'DllUnregisterServer= ?DllUnregisterServer@SymExp@@AAGXXZ 

'注意: 函数名和模块名是区分大小写的 


'找到了解决方案了,但是,由于VB编译完成后就会自动删除OBJ文件, 
'如何再C2生成完OBJ文件后中断编译过程取得OBJ文件呢, 
'网上有种方法就是替换调VB的LINK文件,然后中断一下,将OBJ文件拷贝出来, 
'在用命令行编译。这是个很好的办法,但不够智能化,本人在国外网站上发现了一个更为有效的方法。 

'制作VB的辅助编译工具 
'新建一个工程,命名为LINK,在MAIN过程中加入代码: 

'Public Sub Main() 
'Dim cmd As String 
'Dim fOut As Long 
'Dim sOut As String 
'Dim sDef As String 

'cmd = Command$ 
'If InStr(cmd, "/DLL") > 0 And InStr(cmd, "VBAEXE6.LIB") > 0 Then 
'fOut = InStr(cmd, "/OUT:") 
'sOut = Mid(cmd, fOut + 6, InStr(cmd, "/BASE:") - fOut - 8) 
'sDef = Left(sOut, Len(sOut) - 3) + "def" 
'If Len(Dir(sDef)) Then 
'cmd = cmd & "/DEF:"" " & sDef & " "" " 
'End If 
'End If 
'Shell "LINK32.EXE " & cmd 
'End Sub 
'然后编译成LINK.EXE,先将VB目录下的LINK.EXE改名成LINK32.EXE, 
'再将LINK.EXE拷贝到VB目录下,这样做的好处是不改变原有的编译过程, 
'只是在编译DLL的时候才插入“/DEF:”参数,不会对编译其他程序造成影响。 
'完成了替换操作后,如果要输出其他函数,只需要在程序输出目录下编辑一个 
'和输出文件同名的后缀为“.DEF”的文件就可以了。 
'本人在实现过程中还碰到了一些问题,就是在导出的函数过程中使用很多方法都会有限制, 
'可能是由于VB的一下全局对象未初始化引起的,所以就把注册方法封装到ComRegisterDll.dll中, 
'再去引用,如果不依靠ComRegisterDll.dll而直接将ComRegister放到要注册的 DLL的单元中去 
'引用就会出错,欢迎大家与我一起探讨这个问题的解决方案。 

#2


http://www.china-askpro.com/msg6/qa07.shtml

VB中创建的DLL只是COM组件,无法作为输出函数的DLL,其实这只是个错误的说法。其实MS非常狡猾,如果你是个VB疯狂发烧友的话,应该早就狂试出这种可以创建输出函数的DLL的方法。 
     VB编译文件实际上采取了两次编译的方法,首先是调用C2.exe产生*.OBJ文件,然后调用Link.EXE连接。如果在LINK的时候添加EXPORT选项,实际上是可以输出函数的。但是,在VB的工程选项中将这些屏蔽了。而且过分的是:VB在Build完成后会将OBJ文件删除,这样就无法手动通过Link来创建我们需要的DLL了。不过我找到一个比较龌鹾的变通的方法,就是先创建一个Exe工程,在Form_Load事件里面写下面的语句: 
     
    Sub Main 
     If MsgBox("哈哈", vbOKCancel) = vbOK Then 
     Shell "link2.exe " & Command$ 
     End If 
    End Sub 
     
    然后编译为LinkTemp.EXE,接下来将LINK.EXE改名为Link2.exe,将LinkTemp.EXE改名为Link.EXE。这样在VB调用Link.EXE时会弹出对话框,处理就会中断。这时就可以有机会将OBJ文件拷贝出来了。 
     然后我创建了一个ActiveX DLL工程,在这个工程里面添加一个Module并创建一个Public函数mathadd: 
     
    Public Function mathadd(ByVal a As Long, ByVal b As Long) As Long 
     mathadd = a + b 
    End Function 
     
     编译这个工程,在Link的时候就会中断。然后把创建的Class1.obj、Module1.obj、Project1.obj备份出来。 
     然后就可以调用Link2.exe连接OBJ到DLL了,我的连接代码是: 
     
    Link2.exe "e:\vbdll\Class1.obj" "e:\vbdll\Module1.obj" "e:\vbdll\Project1.obj" "E:\Program Files\Microsoft Visual Studio\VB98\VBAEXE6.LIB" /ENTRY:__vbaS /EXPORT:mathadd /OUT:"e:\vbdll\ProjectOK.dll" /BASE:0x11000000 /SUBSYSTEM:WINDOWS,4.0 /VERS 
     
     注意里面的/ENTRY和/EXPORT开关,/EXPORT开关声明了输出函数mathadd。这样就大功告成了,可以被其他语言引入,例如在VB中,只需要: 
     
    Private Declare Function mathadd Lib "e:\vbdll\ProjectOK.dll" (ByVal a As Long, ByVal b As Long) As Long

#3


好象只能是activeX

#4


可以做成标准dll的,我测试已经成功了

#5


==================DLL的建立================================
1.建立一个新的EXE 内容如下
Private Sub Form_Load() 
    If (MsgBox("编译中暂停.", vbOKCancel) = vbOK) Then
        Shell "link2.exe " & Command$
    End If
    End
End Sub
2.编译为新的EXE为link.exe放置到VB安装的路径中去.修改VB安装路径里原来的link.exe 为 link2.exe

3.建立Activex.dll 

4.添加 Module1

5.在Module1里边加入

Public Function mathadd(ByVal a As Long, ByVal b As Long) As Long
    mathadd = a + b
End Function

Public Function mathdec(ByVal a As Long, ByVal b As Long) As Long
    mathdec = a - b
End Function

6.保存到一定的路径
7.编译dll(注:在提示的时候,先不要点取消,到保存的路径下 把下列文件进行备份)
(1).Class1.OBJ(2)Module1.OBJ(3)Project1.OBJ 放到备份目录中

8.把VB安装路径中的link2.exe 复制到备份目录中
============================重新编译新的DLL==================
9.建立MyLink.bat内容如下:
link2.exe "Class1.obj" "Module1.obj" "Project1.obj" "D:\Program Files\Microsoft Visual Studio\VB98\VBAEXE6.LIB" /ENTRY:__vbaS /EXPORT:mathdec /EXPORT:mathadd /OUT:"ProjectOK.dll" /BASE:0x11000000 /SUBSYSTEM:WINDOWS,4.0 /VERS

注:
(1)/EXPORT:mathdec /EXPORT:mathadd 为导出函数,如果存在多个函数要导出,可加入例:/EXPORT:Function
(2)"ProjectOK.dll" 为编译后的生成的动态库名称

(3)“D:\Program Files\Microsoft Visual Studio\VB98\VBAEXE6.LIB”为你的VB安装路径
===========调用=================================================
10.建立新的工程文件
内容为:
Option Explicit
Private Declare Function mathdec Lib "ProjectOK.dll" (ByVal a As Long, ByVal b As Long) As Long
Private Declare Function mathadd Lib "ProjectOK.dll" (ByVal a As Long, ByVal b As Long) As Long

Private Sub Command1_Click()
 MsgBox mathdec(13, 12)
End Sub

Private Sub Command2_Click()
 MsgBox mathadd(13, 12)
End Sub

11.将文件生成EXE,然后把EXE复制到你生成的ProjectOK.dll的路径下,运行程序..就结束了..

===================================================================


#6


我用五个三角作保证,如果失败了,你可以打我~~~           ^_^

#1


'VB作为一种简单容易上手的语言,可以让开发者快速上手,开发速度快,效率高。但它过分的封装也给开发者带来诸多不便。 

'问题的由来 

'最近本人在开发一个插件结构的项目中就遇到了一个麻烦,我的项目是采用COM架构, 
'框架由DELPHI开发,插件为COM组件,插件可以由其他语言开发,当然也包括VB。 
'每个插件必须注册为一个固定的组件类别(Categories)。 
'在其他语言如VC、DELPHI中实现起来非常简单,只需要重载DllRegisterServer、DllUnregisterServer 
'在两个函数里加入注册注销类别的代码,然后输出就可以了。但到了VB就碰到麻烦了。 

'VB正常情况下是不能直接开发标准DLL,所以也就不支持自定义导出函数, 
'开发ACTIVE DLL的时候,是由VB自动导出必须的四个函数 
'DllGetClassObject,DllCanUnloadNow, DllRegisterServer, DllUnregisterServer。 
'要加入注册注销类别代码就必须重新导出DllRegisterServer, DllUnregisterServer。 

'好了,问题就转换成了如何在VB写的DLL中导出函数了 

'VB编译内幕 
'VB的编译过程大致如下,当我们在编辑环境中编写完代码后,VB调用C2将所有的模块(包括CLASS) 
'编译成OBJ文件(能够为机器语言识别的代码)。一下是C2的一些编译参数说明(E文): 

'- the the name of the prefixed one used for the names of the rowscontaining '' precompilato'', 
'one risen of intermediate tails (from which name of the switch) temporary; 
'these rows are 5 and finish withi suffissi GL, SY, FORMER, IN and DB; they contained are not documented 

'- f the name of the rows to compile 

'- W3 warning level 3, level of '' attenzione'' dedicating to i warnings 

'- Gy it qualifies the connection to level of function (function-level linking) 

'- G5 optimization for the Pentium 

'- Gs4096 it allows not to insert the code for the control of stack (stack probe) if a function does not 

'use more than 4096 byte of stack 

'- dos not documented 

'- Z1 it removes the name of the bookcase of default from the rows.OBJ 

'- Fofileobj the name of rows OBJ to generate (rows output) 

'- Qifdiv it puts in action the corrections for the bug of the division of the Pentium (FDIV bug) 

'- MILILITER it creates rows eseguibile single-threaded 

'- basic it indicates the compiler C2 the fact that the compilation it happens for a plan basic 


'C2完成编译后,VB会调用LINK.EXE将所有的OBJ文件连接成EXE文件,完成编译过程。 
'下面是一段命令行演示如何调用LINK.EXE: 

'LINK C:\Test\Form1.obj C:\Test\Modulo1.obj C:\Test\Progetto1.obj C:\Programmi\Microsoft Visual Studio\VB98\VBAEXE6.lib /ENTRY:__ vbaS /OUT:C:\Test\Progetto1.exe /BASE:0x400000 /SUBSYSTEM:WINDOWS, 4.0 /VERSION:1.0 /DEBUG /DEBUGTYPE:CV /INCREMENTAL:NOT /OPT:REF/MERGE:.rdata =.text /IGNORE:4078 
'对于我们来说这些参数没有什么意义,用默认的就行了。这段命令行中并没有包括输出函数, 
'如果我们希望输出函数,可以定义一个.def文件,按照格式加入要输出的函数列表, 
'然后在命令行后面加上 “/DEF: 文件名”(当然也可以直接加/ EXPORTS参数), 
'再调用命令行编译,用的denpendency工具查看你就会发现你要输出的函数了。 

'Def文件格式的定义: 
'LIBRARY 程序名称 
'Description "MyDLL - (C) Antonio Giuliana, 2004" 
'EXPORTS 
'函数名= ?函数名@函数所在模块名@@AAGXXZ 
'… 

'例: 

'LIBRARY MyDLL 
'Description "MyDLL - (C) Antonio Giuliana, 2004" 
'EXPORTS 
'DllRegisterServer= ?DllRegisterServer@SymExp@@AAGXXZ 
'DllUnregisterServer= ?DllUnregisterServer@SymExp@@AAGXXZ 

'注意: 函数名和模块名是区分大小写的 


'找到了解决方案了,但是,由于VB编译完成后就会自动删除OBJ文件, 
'如何再C2生成完OBJ文件后中断编译过程取得OBJ文件呢, 
'网上有种方法就是替换调VB的LINK文件,然后中断一下,将OBJ文件拷贝出来, 
'在用命令行编译。这是个很好的办法,但不够智能化,本人在国外网站上发现了一个更为有效的方法。 

'制作VB的辅助编译工具 
'新建一个工程,命名为LINK,在MAIN过程中加入代码: 

'Public Sub Main() 
'Dim cmd As String 
'Dim fOut As Long 
'Dim sOut As String 
'Dim sDef As String 

'cmd = Command$ 
'If InStr(cmd, "/DLL") > 0 And InStr(cmd, "VBAEXE6.LIB") > 0 Then 
'fOut = InStr(cmd, "/OUT:") 
'sOut = Mid(cmd, fOut + 6, InStr(cmd, "/BASE:") - fOut - 8) 
'sDef = Left(sOut, Len(sOut) - 3) + "def" 
'If Len(Dir(sDef)) Then 
'cmd = cmd & "/DEF:"" " & sDef & " "" " 
'End If 
'End If 
'Shell "LINK32.EXE " & cmd 
'End Sub 
'然后编译成LINK.EXE,先将VB目录下的LINK.EXE改名成LINK32.EXE, 
'再将LINK.EXE拷贝到VB目录下,这样做的好处是不改变原有的编译过程, 
'只是在编译DLL的时候才插入“/DEF:”参数,不会对编译其他程序造成影响。 
'完成了替换操作后,如果要输出其他函数,只需要在程序输出目录下编辑一个 
'和输出文件同名的后缀为“.DEF”的文件就可以了。 
'本人在实现过程中还碰到了一些问题,就是在导出的函数过程中使用很多方法都会有限制, 
'可能是由于VB的一下全局对象未初始化引起的,所以就把注册方法封装到ComRegisterDll.dll中, 
'再去引用,如果不依靠ComRegisterDll.dll而直接将ComRegister放到要注册的 DLL的单元中去 
'引用就会出错,欢迎大家与我一起探讨这个问题的解决方案。 

#2


http://www.china-askpro.com/msg6/qa07.shtml

VB中创建的DLL只是COM组件,无法作为输出函数的DLL,其实这只是个错误的说法。其实MS非常狡猾,如果你是个VB疯狂发烧友的话,应该早就狂试出这种可以创建输出函数的DLL的方法。 
     VB编译文件实际上采取了两次编译的方法,首先是调用C2.exe产生*.OBJ文件,然后调用Link.EXE连接。如果在LINK的时候添加EXPORT选项,实际上是可以输出函数的。但是,在VB的工程选项中将这些屏蔽了。而且过分的是:VB在Build完成后会将OBJ文件删除,这样就无法手动通过Link来创建我们需要的DLL了。不过我找到一个比较龌鹾的变通的方法,就是先创建一个Exe工程,在Form_Load事件里面写下面的语句: 
     
    Sub Main 
     If MsgBox("哈哈", vbOKCancel) = vbOK Then 
     Shell "link2.exe " & Command$ 
     End If 
    End Sub 
     
    然后编译为LinkTemp.EXE,接下来将LINK.EXE改名为Link2.exe,将LinkTemp.EXE改名为Link.EXE。这样在VB调用Link.EXE时会弹出对话框,处理就会中断。这时就可以有机会将OBJ文件拷贝出来了。 
     然后我创建了一个ActiveX DLL工程,在这个工程里面添加一个Module并创建一个Public函数mathadd: 
     
    Public Function mathadd(ByVal a As Long, ByVal b As Long) As Long 
     mathadd = a + b 
    End Function 
     
     编译这个工程,在Link的时候就会中断。然后把创建的Class1.obj、Module1.obj、Project1.obj备份出来。 
     然后就可以调用Link2.exe连接OBJ到DLL了,我的连接代码是: 
     
    Link2.exe "e:\vbdll\Class1.obj" "e:\vbdll\Module1.obj" "e:\vbdll\Project1.obj" "E:\Program Files\Microsoft Visual Studio\VB98\VBAEXE6.LIB" /ENTRY:__vbaS /EXPORT:mathadd /OUT:"e:\vbdll\ProjectOK.dll" /BASE:0x11000000 /SUBSYSTEM:WINDOWS,4.0 /VERS 
     
     注意里面的/ENTRY和/EXPORT开关,/EXPORT开关声明了输出函数mathadd。这样就大功告成了,可以被其他语言引入,例如在VB中,只需要: 
     
    Private Declare Function mathadd Lib "e:\vbdll\ProjectOK.dll" (ByVal a As Long, ByVal b As Long) As Long

#3


好象只能是activeX

#4


可以做成标准dll的,我测试已经成功了

#5


==================DLL的建立================================
1.建立一个新的EXE 内容如下
Private Sub Form_Load() 
    If (MsgBox("编译中暂停.", vbOKCancel) = vbOK) Then
        Shell "link2.exe " & Command$
    End If
    End
End Sub
2.编译为新的EXE为link.exe放置到VB安装的路径中去.修改VB安装路径里原来的link.exe 为 link2.exe

3.建立Activex.dll 

4.添加 Module1

5.在Module1里边加入

Public Function mathadd(ByVal a As Long, ByVal b As Long) As Long
    mathadd = a + b
End Function

Public Function mathdec(ByVal a As Long, ByVal b As Long) As Long
    mathdec = a - b
End Function

6.保存到一定的路径
7.编译dll(注:在提示的时候,先不要点取消,到保存的路径下 把下列文件进行备份)
(1).Class1.OBJ(2)Module1.OBJ(3)Project1.OBJ 放到备份目录中

8.把VB安装路径中的link2.exe 复制到备份目录中
============================重新编译新的DLL==================
9.建立MyLink.bat内容如下:
link2.exe "Class1.obj" "Module1.obj" "Project1.obj" "D:\Program Files\Microsoft Visual Studio\VB98\VBAEXE6.LIB" /ENTRY:__vbaS /EXPORT:mathdec /EXPORT:mathadd /OUT:"ProjectOK.dll" /BASE:0x11000000 /SUBSYSTEM:WINDOWS,4.0 /VERS

注:
(1)/EXPORT:mathdec /EXPORT:mathadd 为导出函数,如果存在多个函数要导出,可加入例:/EXPORT:Function
(2)"ProjectOK.dll" 为编译后的生成的动态库名称

(3)“D:\Program Files\Microsoft Visual Studio\VB98\VBAEXE6.LIB”为你的VB安装路径
===========调用=================================================
10.建立新的工程文件
内容为:
Option Explicit
Private Declare Function mathdec Lib "ProjectOK.dll" (ByVal a As Long, ByVal b As Long) As Long
Private Declare Function mathadd Lib "ProjectOK.dll" (ByVal a As Long, ByVal b As Long) As Long

Private Sub Command1_Click()
 MsgBox mathdec(13, 12)
End Sub

Private Sub Command2_Click()
 MsgBox mathadd(13, 12)
End Sub

11.将文件生成EXE,然后把EXE复制到你生成的ProjectOK.dll的路径下,运行程序..就结束了..

===================================================================


#6


我用五个三角作保证,如果失败了,你可以打我~~~           ^_^