在一个项目中ASP通过ODBC访问达梦数据库的问题,记录如下:
应用程序使用ASP+ODBC访问DM8数据库,应用通过发布在IIS进行数据访问;
32应用程序运行在windows环境下,在创建32位ODBC驱动后,应用访问报错如下:
Microsoft OLE DB Provider for ODBC Drivers 错误 '80004005'
加密模块加载失败
经过排查发现是属于权限问题,odbc没有权限加载第三方依赖的动态库。因为达梦odbc驱动在windows的dodbc.dll是需要依赖第三方的加密动态库文件的,诸如libeay32.dll ssleay32.dll等,所以需要当前用户具备对达梦程序目录bin下文件的读取权限。有时候我们即时使用windows管理员账户登录后安装达梦数据库程序,会发现程序目录bin目录带有锁标志,表示当前用户对此目录没有访问权限,这时候需要我们手动对此文件夹中的文件进行权限开放,粗暴一点的方法就是对文件夹添加EVERYONE用户并授予“完全控制”权限并进行继承授权。
关于ODBC相关的几个错误记录如下:
- "在指定的 DSN 中,驱动程序和应用程序之间的体系结构不匹配"
分析:此报错比较容易解决,属于应用程序与使用的ODBC位数不匹配导致的,例如应用程序以32位运行,连接了64位ODBC的DSN则会报这个错。
解决方法:应使用应用程序对应位数的ODBC数据源,即可解决此问题。
备注:关于ASP应用发布在IIS上的问题,即使发布在64位操作系统下的ASP应用在IIS上其实也可以以32位应用模式运行,可以在ASP应用对应的IIS连接池上查看,默认都是False的,如果是True则表示这个应用是以32位运行模式运行的。如下图:
2.加密模块加载失败”,或者“Microsoft OLE DB Provider for ODBC Drivers 错误 '80004005' 由于系统错误 5: 拒绝访问。”
分析:属于权限问题,odbc驱动没有权限加载第三方依赖的动态库
解决方法:
(1).系统环境变量是否设置了达梦程序bin目录路径;
(2).当前用户是否有访问程序目录bin下文件的权限,windows server安装完达梦后,程序目录bin文件夹可能带有锁标志,即无法访问里面的文件,需要在bin文件夹上“属性”-“安全”-添加“EVERYONE”用户并授予“完全控制”权限;
3.加密模块版本不匹配”
分析:属于odbc加载到了对应的第三方动态库文件,但是加载的是错误的动态库文件。dodbc.dll是需要依赖第三方动态库文件的,例如比较重要的两个libeay32.dll ssleay32.dll都属于openSSL相关的动态链接库,而windows操作系统c:\windows\sysWOW64下大多自带这些动态库,但是有些较老的windows版本,例如windows server2008自带的并不是达梦dodbc.dll所需要依赖的(即使文件名称相同),所以我们只需要让系统加载到正确的动态库文件即可。分析到这里我们可能会想到直接将达梦bin目录添加WINDOWS的系统环境变量PATH优先级最高位置是不是就可以了。笔者实际操作发现是不行的,怀疑可能windows操作系统启动后自动加载了根盘下的动态库,而设置的系统环境变量path还是处于较低优先级。优先级这个问题有待进一步确定。
解决方法:达梦dodbc.dll加密需要的第三方动态库与机器上已有的动态库发生冲突,解决办法将达梦bin下的*.dll替换拷贝到c:\WINDOWS\SysWOW64下即可(替换中发现了共替换了5个文件libeay32.dll,msvcp100.dll,msvcp100d.dll,msvcr100.dll,msvcr100d.dll,其中libeay32.dll是最重要的一个)
附件给出一个访问odbc数据源的vbs样例,需要可以下载使用测试访问ODBC数据源。
Dim objConnection 'CONNECTION对象实例
Dim objRecordSet 'RECORDSET对象实例
Dim objCommand '命令对象实例
Dim strConnectionString '连接字符串
Sub ConnectDatabase()
Set objConnection = CreateObject("ADODB.CONNECTION") '1 - 建立CONNECTION对象的实例
strConnectionString = "Dsn=DM;uid=SYSDBA;pwd=SYSDBA" '2 - 建立连接字符串
objConnection.Open strConnectionString
Set objRecordSet = CreateObject("ADODB.RECORDSET") '4 - 建立RECORDSET对象实例
Set objCommand = CreateObject("ADODB.COMMAND") '5 - 建立COMMAND对象实例
objCommand.ActiveConnection = objConnection
objCommand.CommandText = "select * FROM TEST"
objRecordSet.CursorLocation = 3
objRecordSet.Open objCommand '6 - 执行SQL语句,将结果保存在RECORDSET对象实例中
intArrayLength = objRecordSet.RecordCount '将查询结果的行数作为数组的长度
MsgBox "查询结果集总数为:" & intArrayLength
End Sub
ConnectDatabase