国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 開發(fā) > 綜合 > 正文

VB中定制DllRegisterServer、DllUnregisterServer

2024-07-21 02:21:05
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
vb中定制dllregisterserver、dllunregisterserver

-阿鬼(heroyin)

vb作為一種簡(jiǎn)單容易上手的語(yǔ)言,可以讓開發(fā)者快速上手,開發(fā)速度快,效率高。但它過(guò)分的封裝也給開發(fā)者帶來(lái)諸多不便。

問(wèn)題的由來(lái)
最近本人在開發(fā)一個(gè)插件結(jié)構(gòu)的項(xiàng)目中就遇到了一個(gè)麻煩,我的項(xiàng)目是采用com架構(gòu),框架由delphi開發(fā),插件為com組件,插件可以由其他語(yǔ)言開發(fā),當(dāng)然也包括vb。每個(gè)插件必須注冊(cè)為一個(gè)固定的組件類別(categories)。在其他語(yǔ)言如vc、delphi中實(shí)現(xiàn)起來(lái)非常簡(jiǎn)單,只需要重載dllregisterserver、dllunregisterserver在兩個(gè)函數(shù)里加入注冊(cè)注銷類別的代碼,然后輸出就可以了。但到了vb就碰到麻煩了。

vb正常情況下是不能直接開發(fā)標(biāo)準(zhǔn)dll,所以也就不支持自定義導(dǎo)出函數(shù),開發(fā)active dll的時(shí)候,是由vb自動(dòng)導(dǎo)出必須的四個(gè)函數(shù)dllgetclassobject, dllcanunloadnow, dllregisterserver, dllunregisterserver。要加入注冊(cè)注銷類別代碼就必須重新導(dǎo)出dllregisterserver, dllunregisterserver。

好了,問(wèn)題就轉(zhuǎn)換成了如何在vb寫的dll中導(dǎo)出函數(shù)了

vb編譯內(nèi)幕
vb的編譯過(guò)程大致如下,當(dāng)我們?cè)诰庉嫮h(huán)境中編寫完代碼后,vb調(diào)用c2將所有的模塊(包括class)編譯成obj文件(能夠?yàn)闄C(jī)器語(yǔ)言識(shí)別的代碼)。一下是c2的一些編譯參數(shù)說(shuō)明(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會(huì)調(diào)用link.exe將所有的obj文件連接成exe文件,完成編譯過(guò)程。下面是一段命令行演示如何調(diào)用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
對(duì)于我們來(lái)說(shuō)這些參數(shù)沒有什么意義,用默認(rèn)的就行了。這段命令行中并沒有包括輸出函數(shù),如果我們希望輸出函數(shù),可以定義一個(gè).def文件,按照格式加入要輸出的函數(shù)列表,然后在命令行后面加上 “/def: 文件名”(當(dāng)然也可以直接加/ exports參數(shù)),再調(diào)用命令行編譯,用的denpendency工具查看你就會(huì)發(fā)現(xiàn)你要輸出的函數(shù)了。

def文件格式的定義:



library 程序名稱

description "mydll - (c) antonio giuliana, 2004"

exports

函數(shù)名= ?函數(shù)名@函數(shù)所在模塊名@@aagxxz



例:

library mydll

description "mydll - (c) antonio giuliana, 2004"

exports

dllregisterserver= [email protected]@@aagxxz

dllunregisterserver= [email protected]@@aagxxz



注意:函數(shù)名和模塊名是區(qū)分大小寫的



找到了解決方案了,但是,由于vb編譯完成后就會(huì)自動(dòng)刪除obj文件,如何再c2生成完obj文件后中斷編譯過(guò)程取得obj文件呢,網(wǎng)上有種方法就是替換調(diào)vb的link文件,然后中斷一下,將obj文件拷貝出來(lái),在用命令行編譯。這是個(gè)很好的辦法,但不夠智能化,本人在國(guó)外網(wǎng)站上發(fā)現(xiàn)了一個(gè)更為有效的方法。

制作vb的輔助編譯工具
新建一個(gè)工程,命名為link,在main過(guò)程中加入代碼:

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目錄下,這樣做的好處是不改變?cè)械木幾g過(guò)程,只是在編譯dll的時(shí)候才插入“/def:”參數(shù),不會(huì)對(duì)編譯其他程序造成影響。

完成了替換操作后,如果要輸出其他函數(shù),只需要在程序輸出目錄下編輯一個(gè)和輸出文件同名的后綴為“.def”的文件就可以了。

開始替換dllregisterserver、dllunregisterserver
1、制作注冊(cè)和注銷的工具庫(kù)comregisterdll

新建一個(gè)工程,引入兩個(gè)庫(kù):isa helper com component 1.0 type library和 typelib information。再創(chuàng)建一個(gè)類comregister,在comregister類中實(shí)現(xiàn)一個(gè)方法:

regtypelib(slib as string, byval bstate as boolean)用來(lái)實(shí)現(xiàn)注冊(cè)和注銷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為模塊名稱,無(wú)須路徑和后綴 bstate 為false時(shí)是注銷,反之為注冊(cè)

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,注冊(cè)。這個(gè)庫(kù)為公用庫(kù),所有需要重新定制dllregisterserver、dllunregisterserver的工程都可以方便的引用它來(lái)方便的完成注冊(cè)和注銷過(guò)程。



2、定制dllregisterserver、dllunregisterserver

新建一個(gè)工程mydll,引入comregiterdll.dll,添加一個(gè)module mainmodule,在mainmodule中新建兩個(gè)函數(shù)dllregisterserver、dllunregisterserver:



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, ”注冊(cè)過(guò)程”, “mydll”, 0



dllregisterserver = comreg.regtypelib("mydll", true)

end function



public function dllunregisterserver() as long

dim comreg as comregister

set comreg = new comregister

‘加入你的處理代碼

messagebox 0, ”注銷過(guò)程”, “mydll”, 0



dllunregisterserver = comreg.regtypelib("mydll", false)

end function

在程序目錄中新建一個(gè)mydll.def,def文件內(nèi)容如下:

library mydll

description "mydll - (c) antonio giuliana, 2004"

exports

dllregisterserver= [email protected] mainmodule @@aagxxz

dllunregisterserver= [email protected] mainmodule @@aagxxz

保存,編譯,運(yùn)行regsvr32注冊(cè)mydll你就發(fā)現(xiàn)彈出對(duì)話框“注冊(cè)過(guò)程“

結(jié)束語(yǔ)
本人使用導(dǎo)出函數(shù)的方法引自:http://www.visual-basic.it/uploads/articoli/tecnici/agdllbyvb.htm

本人在實(shí)現(xiàn)過(guò)程中還碰到了一些問(wèn)題,就是在導(dǎo)出的函數(shù)過(guò)程中使用很多方法都會(huì)有限制,可能是由于vb的一下全局對(duì)象未初始化引起的,所以就把注冊(cè)方法封裝到comregisterdll.dll中,再去引用,如果不依靠comregisterdll.dll而直接將comregister放到要注冊(cè)的dll的單元中去引用就會(huì)出錯(cuò),歡迎大家與我一起探討這個(gè)問(wèn)題的解決方案。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 永泰县| 图们市| 广河县| 醴陵市| 左贡县| 南部县| 潼南县| 桦川县| 五家渠市| 镇康县| 石楼县| 锡林浩特市| 永和县| 宁明县| 德化县| 嘉义县| 故城县| 岫岩| 陆良县| 集安市| 安西县| 富锦市| 五大连池市| 聊城市| 海丰县| 寻甸| 鲁山县| 绥宁县| 衡东县| 克东县| 东至县| 福州市| 巴林右旗| 花垣县| 福海县| 长治县| 甘南县| 蓬莱市| 庄浪县| 和硕县| 高唐县|