`
cgs1999
  • 浏览: 530258 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

VB中定制DllRegisterServer、DllUnregisterServer

 
阅读更多

VB中定制DllRegisterServer、DllUnregisterServer

作者:hero_yin
<script type="text/javascript"><!-- google_ad_client = "pub-4911831409822175"; google_ad_width = 300; google_ad_height = 250; google_ad_format = "300x250_as"; google_ad_type = "text_image"; google_ad_channel ="1609457216"; google_color_border = "FFFFFF"; google_color_link = "000000"; google_color_bg = "FFFFFF"; google_color_text = "CCCCCC"; google_color_url = "CCCCCC"; //--></script><script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"> </script>

VB中定制DllRegisterServerDllUnregisterServer

-阿鬼(heroyin

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

问题的由来

最近本人在开发一个插件结构的项目中就遇到了一个麻烦,我的项目是采用COM架构,框架由DELPHI开发,插件为COM组件,插件可以由其他语言开发,当然也包括VB。每个插件必须注册为一个固定的组件类别(Categories)。在其他语言如VCDELPHI中实现起来非常简单,只需要重载DllRegisterServerDllUnregisterServer在两个函数里加入注册注销类别的代码,然后输出就可以了。但到了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文件呢,网上有种方法就是替换调VBLINK文件,然后中断一下,将OBJ文件拷贝出来,在用命令行编译。这是个很好的办法,但不够智能化,本人在国外网站上发现了一个更为有效的方法。

制作VB的辅助编译工具

新建一个工程,命名为LINK,在MAIN过程中加入代码:

Public Sub <place w:st="on">Main</place>()

 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”的文件就可以了。

开始替换DllRegisterServerDllUnregisterServer

1、制作注册和注销的工具库ComRegisterDll

新建一个工程,引入两个库:ISA helper Com component 1.0 type library TypeLib Information。再创建一个类ComRegister,在ComRegister类中实现一个方法:

RegTypelib(sLib As String, ByVal bState As Boolean)用来实现注册和注销ACTIVEX。代码如下:

Option Explicit

Public Type GUID

Data1 As Long

Data2 As Integer

Data3 As Integer

Data4(0 To 7) As Byte

End Type

Private Enum eSYSKIND

SYS_WIN16 = 0&

SYS_WIN32 = 1&

SYS_MAC = 2&

End Enum

Private Declare Function LoadTypeLib Lib "oleaut32.dll" ( _

pFileName As Byte, pptlib As Object) As Long

Private Declare Function RegisterTypeLib Lib "oleaut32.dll" ( _

ByVal ptlib As Object, szFullPath As Byte, _

szHelpFile As Byte) As Long

Private Declare Function UnRegisterTypeLib Lib "oleaut32.dll" ( _

libID As GUID, _

ByVal wVerMajor As Integer, _

ByVal wVerMinor As Integer, _

ByVal lCID As Long, _

ByVal tSysKind As eSYSKIND _

) As Long

Private Declare Function CLSIDFromString Lib "ole32.dll" (lpsz As Byte, pclsid As GUID) As Long

Private Declare Function GetModuleFileName Lib "kernel32" Alias "GetModuleFileNameA" (ByVal hModule As Long, ByVal lpFileName As String, ByVal nSize As Long) As Long

Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long

取得模块的路径

Private Function GetModulePath(bModuleName As String) As String

Dim ModleId As Long

Dim Path As String * 254

ModleId = GetModuleHandle(bModuleName)

Call GetModuleFileName(ModleId, Path, 254)

GetModulePath = Path

End Function

‘sLib为模块名称,无须路径和后缀 bState FALSE时是注销,反之为注册

Public Function RegTypelib(sLib As String, ByVal bState As Boolean, ByVal bType As PSDK.EPluginCategory) As Long

Dim suLib() As Byte

Dim errOK As Long

Dim tlb As Object

Dim cTLI As TypeLibInfo

Dim tGUID As GUID, sCLSID As String

Dim iMajor As Integer, iMinor As Integer

Dim lCID As Long

Dim DllPath As String

DllPath = GetModulePath(sLib)

If bState Then

'''' Basic automatically translates strings to Unicode Byte arrays

'''' but doesn''''t null-terminate, so you must do it yourself

suLib = DllPath & vbNullChar

'''' Pass first byte of array

errOK = LoadTypeLib(suLib(0), tlb)

If errOK = 0 Then

errOK = RegisterTypeLib(tlb, suLib(0), 0)

End If

RegTypelib = errOK

Else

Set cTLI = TLI.TypeLibInfoFromFile(DllPath)

sCLSID = cTLI.GUID

iMajor = cTLI.MajorVersion

iMinor = cTLI.MinorVersion

lCID = cTLI.lCID

Set cTLI = Nothing

suLib = sCLSID & vbNullChar

errOK = CLSIDFromString(suLib(0), tGUID)

If errOK = 0 Then

errOK = UnRegisterTypeLib(tGUID, iMajor, iMinor, lCID, SYS_WIN32)

RegTypelib = errOK

End If

End If

End Function

将工程编译成ComRegiterDll.dll,注册。这个库为公用库,所有需要重新定制DllRegisterServerDllUnregisterServer的工程都可以方便的引用它来方便的完成注册和注销过程。

2、定制DllRegisterServerDllUnregisterServer

新建一个工程MyDll,引入ComRegiterDll.dll,添加一个MODULE mainmodule,在mainmodule中新建两个函数DllRegisterServerDllUnregisterServer

Declare Function MessageBox Lib "user32" Alias "MessageBoxA" (ByVal hwnd As Long, ByVal lpText As String, ByVal lpCaption As String, ByVal wType As Long) As Long

Public Function DllRegisterServer() As Long

Dim ComReg As ComRegister

Set ComReg = New ComRegister

加入你的处理代码

MessageBox 0, ”注册过程”, “MYDLL”, 0

DllRegisterServer = ComReg.RegTypelib("MyDll", True)

End Function

Public Function DllUnregisterServer() As Long

Dim ComReg As ComRegister

Set ComReg = New ComRegister

加入你的处理代码

MessageBox 0, ”注销过程”, “MYDLL”, 0

DllUnregisterServer = ComReg.RegTypelib("MyDll", False)

End Function

在程序目录中新建一个mydll.defdef文件内容如下:

LIBRARY MyDLL

DESCRIPTION "MyDLL - (C) Antonio Giuliana, 2004"

EXPORTS

DllRegisterServer= ?DllRegisterServer@ mainmodule @@AAGXXZ

DllUnregisterServer= ?DllUnregisterServer@ mainmodule @@AAGXXZ

保存,编译,运行regsvr32注册mydll你就发现弹出对话框“注册过程“

结束语

本人使用导出函数的方法引自:http://www.visual-basic.it/uploads/articoli/tecnici/agDllByVB.htm

本人在实现过程中还碰到了一些问题,就是在导出的函数过程中使用很多方法都会有限制,可能是由于VB的一下全局对象未初始化引起的,所以就把注册方法封装到ComRegisterDll.dll中,再去引用,如果不依靠ComRegisterDll.dll而直接将ComRegister放到要注册的DLL的单元中去引用就会出错,欢迎大家与我一起探讨这个问题的解决方案。

分享到:
评论

相关推荐

    windows7注册DLL找不到入口点dllregisterserver怎么办.mp4

    大家好 今天教大家“windows7注册DLL找不到入口点dllregisterserver怎么办” 看我操作 开始 运行 你们自己找找吧 我把快捷方式提出来了 regsvr32 dll的名字 发现弹出这个错误 我们要用管理员权限执行命令提示符 ...

    Register COM DLL(注册DLL的API组件)

    Delphi源代码,内附VB6动态注册DLL的DEMO

    易语言rmvb播放

    易语言rmvb播放源码,rmvb播放,DllRegisterServer,DllUnregisterServer,SetParent,SetWindowPos,SetWindowRect,GetWindowLongA,SetWindowLongA

    com 编程(关于com编程的知识)

    所有的进程内com服务器输出四个标准函数:dllregisterserver、dllunregisterserver、dllgetclassobject和dllcanunloadnow。根据字面意思,我们也已经可以感觉的出这些函数的工作都会是什么。当然,delphi已经为我们...

    易语言COM演示源码,易语言COM类继承演示

    易语言COM类继承演示源码,COM类继承演示,Dll入口函数,DllCanUnloadNow,DllGetClassObject,DllRegisterServer,DllUnregisterServer,ToDword,构造com函数,CLSIDToString,StringToCLSID,A2W,W2A,取文本型指针,取字节集...

    易语言系统工具应用

    易语言系统工具应用源码,系统工具应用,一键关机,灰色按钮克星,文件粉碎机,重建图标缓存,启动项管理,系统校时,注册表管理,Windows防火墙,AddUser,DelUser,autorun,按键记录,DllRegisterServer,DllUnregisterServer,...

    DirectShow过滤器-抓取样本过滤器

    DLL注册函数名:DllRegisterServer 删除注册函数名:DllUnregisterServer 过滤器有1个输入引脚。 输入引脚标识:In 输入引脚媒体类型: 主要类型:GUID_NULL 子类型:GUID_NULL 格式类型:GUID_NULL 在一个过滤器图...

    DirectShow过滤器-获取系统播放的声音过滤器

    本过滤器获取系统播放的声音。...DLL注册函数名:DllRegisterServer 取消注册函数名:DllUnregisterServer 已在win7,8,10系统下做过测试,可以正常使用。其它系统下没有测试。 另附DLL注册软件一个。

    DirectShow过滤器-读音频文件过滤器

    DLL注册函数名:DllRegisterServer 删除注册函数名:DllUnregisterServer 过滤器有1个输出引脚。 输出引脚标识:1 输出引脚媒体类型: 主要类型:MEDIATYPE_Audio 子类型:MEDIASUBTYPE_PCM 格式类型:FORMAT_...

    DirectShow过滤器-视频渲染过滤器

    DLL注册函数名:DllRegisterServer 删除注册函数名:DllUnregisterServer 过滤器接口:IBaseFilter,IBasicVideo,IMediaSeeking,IQualProp,IQualityControl,ISpecifyPropertyPages,IVideoWindow 输入引脚标识:...

    组态王6.5源代码

    组态王6.5源代码 zutai1 zutai2 zutai3 zutai4 zutai5 LIBRARY "METER.OCX" EXPORTS DllCanUnloadNow @1 PRIVATE DllGetClassObject @2 PRIVATE DllRegisterServer @3 PRIVATE DllUnregisterServer @4 PRIVATE

    TestCom.zip

    1. 用DLLRegisterServer/DllUnregisterServer向注册表注册/卸载组件; 2. 使用CoCreateInstance 直接创建组件; 3. 使用CoGetClassObject 获取类厂,通过类厂CreateInstance创建组件; 4. 注册组件时,命令行用管理...

    COM技术初探(pdf格式)

    1.3.2 DllRegisterServer()和DllUnregisterServer() 1.4 MathCOM.cpp文件 1.5 小结 2. 实现ISmipleMath,IAdvancedMath接口和DllGetClassObject() 2.1 实现ISmipleMath和IAdvancedMath接口 2.2 COM组件调入大致过程 ...

    DirectShow过滤器-读MP4视频文件过滤器

    DLL注册函数名:DllRegisterServer 删除注册函数名:DllUnregisterServer 视频输出引脚媒体类型: 主要类型:MEDIATYPE_Video 子类型:MEDIASUBTYPE_RGB32 格式类型:FORMAT_VideoInfo 样本为固定大小。 不使用时间...

    VC++在程序中用代码注册和卸载ocx控件

    VC++在程序中用代码注册和卸载ocx控件,在... 一般情况下,控件的OCX文件中已包含有DLLRegisterServer和DLLUnregisterServer函数,我们只需调用它们便可实现OCX控件的注册与卸载。 运行环境:Windows/Visual C/C++

    DirectShow过滤器-写MP4视频文件过滤器

    DLL注册函数名:DllRegisterServer 删除注册函数名:DllUnregisterServer 视频引脚媒体类型: 主要类型:MEDIATYPE_Video 子类型:MEDIASUBTYPE_RGB32 格式类型:FORMAT_VideoInfo 样本为固定大小。 不使用时间压缩...

    DirectShow过滤器-读视频文件过滤器

    本过滤器读取视频文件,将读取到的视频数据解码为未压缩的视频流RGB32,由视频引脚输出。...DLL注册函数名:DllRegisterServer 删除注册函数名:DllUnregisterServer 过滤器有2个输出引脚,视频引脚和音频引脚。

    DirectShow过滤器-写视频文件过滤器

    DLL注册函数名:DllRegisterServer 删除注册函数名:DllUnregisterServer 有2个输入引脚。 视频引脚媒体类型: 主要类型:MEDIATYPE_Video 子类型:MEDIASUBTYPE_RGB32 音频引脚脚媒体类型: 主要类型:MEDIATYPE_...

    DirectShow过滤器-获取过滤器图事件过滤器

    本过滤器获取过滤器图事件,将事件代码及参数以列表形式显示在窗口中。 ... 过滤器名称:事件 过滤器GUID:{380338B5-4292-...DLL注册函数名:DllRegisterServer 删除注册函数名:DllUnregisterServer 过滤器没有引脚。

    ATLVC源代码:DllUnregisterServer_MFC_Impl

    ATL源代码:DllUnregisterServer_MFC_Impl 关键字:DllUnregisterServer_MFC_Impl,ATL

Global site tag (gtag.js) - Google Analytics