|
经常编写一些vba工具,最近在实践采用dll封装vba代码,然后excel去调用dll的方法,不可避免需要注册编写的dll,经常遇到注册失败的情况,现将总结的经验分享给大家。
vba代码写在excel2007中,dll使用vb6.0开发,操作系统是win7 64位。
因为在win7下,注册dll需要管理员权限,因此在vba中用shell方法注册dll基本不可行了。最早想到的注册方法是制作批处理文件,用管理员权限运行,但是经历了多次失败。
本文就是总结多次失败的经验教训,希望能为其他朋友节省一些弯路。
如果您的操作系统是32位的,大概不会遇到我的问题,因此可不用看本文。
一、注册失败的情况:
最初编写的注册bat文件:
@ ECHO OFF
cd /d %~dp0
copy compdll.dll %windir%\system32\
Regsvr32 %windir%\system32\compdll.dll
注册失败,提示找不到模块。但是在system32目录下compdll.dll文件是存在的。
二、失败原因探讨:
原文链接:http://www.cnblogs.com/hbccdf/p/dllchecktoolandsyswow64.html?utm_source=tuicool
缘生梦 在博文中很详细的讲解了system32目录与syswow64目录的区别,总结如下(win7系统):
1 64位程序访问system32文件夹中的文件,可直接访问(包括拷贝,读取,删除)
2 32位程序访问system32文件夹,会被自动重新定向到syswow64目录(包括拷贝,读取,删除)
3 如:一个32位的软件执行 copy 1.txt %windir%\system32\ 最后1.txt会出现在%windir%\syswow64\ 目录
4 system32和syswow64目录下各有一个Regsvr32.exe 文件,这两个Regsvr32.exe分别是64位和32位的程序。没错,system32目录下的Regsvr32.exe是64位的,syswow64下的Regsvr32.exe是32位的。
5 缘生梦的博文中阐述的很详细了,win7的system32文件夹就是设计来放64位程序或者com组件的,syswow64才是系统设计用来放32程序的。
回到实践中的bat文件,注册32位dll失败的原因总结:
1 win7下的cmd程序实际上是64位的程序,因此copy compdll.dll %windir%\system32\ 是真正的将dll拷贝到system32文件夹
2 cmd的当前目录不是在syswow64目录下的时候,运行 Regsvr32 %windir%\system32\compdll.dll,会默认调用64位的Regsvr32.exe,因此本指令实际操作是要注册system32目录下的compdll.dll。因为compdll.dll是32位的,放在system32目录下注册,会注册失败,提示找不到模块(应该是操作系统设定的,不允许32位dll在system32目录下进行注册)
3 如果将dll放在非system32目录下,比如放在c:\或者 %windir%或者syswow64或者其他任何目录下,注册会成功。
cd /d %~dp0
copy compdll.dll %windir%\
Regsvr32 %windir%\compdll.dll
注册成功
4 如果将dll放在syswow64目录下,同时将当前目录调整到syswow64目录下,运行regsvr32程序,这时实际上运行的是32位的regsvr32程序,这时运行以下两个指令都能成功:
cd /d %~dp0
copy compdll.dll %windir%\syswow64
Regsvr32 %windir%\syswow64\compdll.dll
或者:
cd /d %~dp0
copy compdll.dll %windir%\syswow64
Regsvr32 %windir%\system32\compdll.dll
都能注册成功。
原因如缘生梦所论述的,这时的regsvr32是32位的程序,注册system32会自动重定向到syswow64目录,因此以上两段代码实际上都是注册的syswow64目录下的dll
总的来说,就是32位的dll不能放在system32下注册。32位和64位的regsvr32都可注册不放在system32目录下的dll。32位和64位的regsvr32的区别就是前者能实现system32重新定向到syswow64,后者不能。
以上提到的bat需要使用管理员权限运行方可正确注册。
因为cmd是64位的,dll是32位的,因此用bat注册就经常会出错。
三、制作安装程序是更好的选择:
最好的方法还是用vb写一个32位的注册程序,如果在32位系统安装就能在system32中注册dll,在64位系统中安装就能自动copy和注册在syswow64目录下。而注册程序中的代码只需要写system32,因此这样的方法比使用bat注册的通用性更好。
制作安装和卸载程序时,vb的工程描述中,写入 setup ,就能编译为带管理员权限的exe。
安装:
Sub Main()
str1 = Replace(App.Path & "\compdll.dll", "\\", "\") 'replace为了防止app.path是根目录的时候出现"\\"
str2 = Environ("SystemRoot") & "\system32\compdll.dll"
FileCopy str1, str2
Shell "regsvr32 /s " & Environ("SystemRoot") & "\system32\compdll.dll"
End Sub
卸载:
Sub Main()
Shell "regsvr32 /u /s " & Environ("SystemRoot") & "\system32\compdll.dll"
End Sub
四、最后请教大家一个问题:
如果我将dll放在了system32目录,并且注册了。随后我将system32中的dll文件剪切到了调用该dll的程序的目录下,我测试的结果应该是不能调用了。有没有什么方法,能够让一个程序,在原注册位置找不到dll的情况下,自动的到本程序目录下找到这个dll呢? |
|