Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1164547
  • 博文数量: 1310
  • 博客积分: 3980
  • 博客等级: 中校
  • 技术积分: 8005
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-09 22:05
文章分类

全部博文(1310)

文章存档

2011年(1)

2008年(1309)

我的朋友

分类:

2008-05-24 08:29:08

  在使用 VC、 VB、 Delphi等高级语言编写数据库应用程序时,往往需要用户自己在控制面板中配置 ODBC数据源。对于一般用户而言,配置 ODBC数据源可能是一件比较困难的工作。而且,在实际应用中,用户往往要求在同一个应用程序中访问不同的数据源,因此采用一般的加载方法就有了无法克服的缺陷。为能在程序中完成这一工作,方便应用程序的使用,本文以 VC为开发环境介绍两种在应用程序中动态加载 ODBC系统数据源的方法。 

  方法一:修改注册表 

  设计思路 

  一般情况下,当用户在控制面板中配置好 ODBC数据源后, Windows系统便在注册表中加入了一些子键来存储用户的配置结果。当应用程序需要用到数据源时, Windows便会通知底层接口查阅注册表中该数据源的配置。如果用户删除了某个 ODBC数据源,那么也会在注册表中有所反应。如果配置的数据源是用户数据源, Windows系统便会修改注册表的 HKEY_CURRENT_USER\SOFTWARE\ODBC\ODBC.INI子键;如果配置的数据源是系统数据源, Windows系统便会修改注册表的 HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC. 

  INI主键。因此,我们可以在应用程序中使用 Windows API中的注册表编辑函数来完成 Windows所做的工作,这样就可以达到动态加载数据源的目的。具体实现对于不同类型的数据源,注册表的修改也各有不同,但基本上都要修改两个地方。一个是在 ODBC.INI子键下建立一个与数据源描述名同名的子键,并在该子键下建立与数据源配置相关的项;另一个是在 \ODBC.INI\ODBC Data Sources子键下建立一个新项以便告诉驱动程序管理器 ODBC数据源的类型。下面以配置一个 Microsoft Access数据源为例给出实现此功能的函数的代码。 

/* strSourceName是要创建的数据源名, strSourceDb是数据库存放路径, strDescription是数据源的描述字符串。* / 

BOOL CLoadOdbcDlg:: LoadDbSource(CString strSourceName,CString strSourceDb, CString strDescription) 



//存放打开的注册表键 

HKEY hKey; 

DWORD dw; 

//存放注册表 API函数执行的返回值 

LONG lReturn; 

//存放要打开的子键 

CString strSubKey; 

//检测是否安装了 MS Access ODBC driver:odbcjt32.dll 

//获得 Windows系统目录 

char sysDir[MAX_PATH]; 

char drvName[]=" \\odbcjt32.dll" ; 

::GetSystemDirectory (sysDir,MAX_PATH); 

strcat(sysDir,drvName); 

CFileFind findFile; 

if(!findFile.FindFile (sysDir)) 



AfxMessageBox("您的计算机系统中没有安装 MS Access的 ODBC驱动程序 odbcjt32.dll,您将无法加载该类数据源。 " ,MB_OK|MB_ICONSTOP); 

return false; 



strSubKey=" SOFTWARE\\ODBC\\ODBC.INI\\"+ strSourceName; 
//创建 ODBC数据源在注册表中的子键 

lReturn=::RegCreateKeyEx(HKEY_LOCAL_ 

MACHINE,(LPCTSTR)strSubKey,0,NULL,REG_OPTION 

_NON_VOLATILE,KEY_WRITE,NULL,& hKey,& dw); 

if(lReturn != ERROR_SUCCESS) 

return false; 

//设置数据源的各项参数 

CString strDbq=strSourceDb; 

CString strDriver=sysDir; 

DWORD dwDriverId=25; 

CString strFil=" MS Access" ; 

CString strPwd=strSourceName; 

DWORD dwSafeTransactions=0; 

CString strUid=strSourceName; 

::RegSetValueEx (hKey," DBQ" ,0L,REG_SZ, 

(CONST BYTE* )((LPCTSTR) strDbq),strDbq .GetLength ()) ; ::RegSetValueEx (hKey," Description" ,0L,REG_SZ,(CONST BYTE* )((LPCTSTR)strDescription),strDescription.GetLength()); 

::RegSetValueEx (hKey," Driver" ,0L,REG_SZ,(CONST BYTE* )((LPCTSTR)strDriver),strDriver .GetLength ()); 

::RegSetValueEx (hKey," DriverId" ,0L,REG_DWORD,(CONST BYTE* )(& dwDriverId),sizeof(dw)); 

::RegSetValueEx (hKey," FIL" ,0L,REG_SZ, 

(CONST BYTE* )((LPCTSTR) strFil),strFil .GetLength ()); 

::RegSetValueEx (hKey," PWD" ,0L,REG_SZ, 

(CONST BYTE* )((LPCTSTR)strPwd),strPwd.GetLength ()) ; ::RegSetValueEx (hKey," SafeTransactions" ,0L, 

REG_DWORD,(CONST BYTE* )(& dwSafeTransactions),sizeof(dw)); 

::RegSetValueEx (hKey," UID" ,0L,REG_SZ, 

(CONST BYTE* )((LPCTSTR)strUid),strUid .GetLength ()); ::RegCloseKey(hKey); 

//创建 ODBC数据源的 Jet子键 

strSubKey+ =" \\Engines\\Jet" ; 

lReturn=::RegCreateKeyEx (HKEY_LOCAL_MACHINE ,(LPCTSTR)strSubKey,0,NULL,REG_OPTION_NON_ 

VOLATILE,KEY_WRITE,NULL,& hKey,& dw); 

if(lReturn != ERROR_SUCCESS) 

return false; 

//设置该子键下的各项参数 

CString strImplict=" " ; 

CString strUserCommit=" Yes" ; 

DWORD dwPageTimeout=5; 

DWORD dwThreads=3; 

DWORD dwMaxBufferSize=2048; 

::RegSetValueEx (hKey," ImplictCommitSync" ,0L,REG_SZ,(CONST BYTE* )((LPCTSTR)strImplict),strImplict.GetLength ()+ 1); 

::RegSetValueEx (hKey," MaxBufferSize" ,0L,REG_DWORD,(CONST BYTE* )(& dwMaxBufferSize),sizeof(dw)); 

::RegSetValueEx (hKey," PageTimeout" ,0L,REG_DWORD,(CONST BYTE* )(& dwPageTimeout),sizeof(dw)); 

::RegSetValueEx (hKey," Threads" ,0L,REG_DWORD,(CONST BYTE* )(& dwThreads),sizeof(dw)); 

::RegSetValueEx (hKey," UserCommitSync" ,0L,REG_SZ,(CONST BYTE* )((LPCTSTR)strUserCommit),strUserCommit.GetLength ()); 

::RegCloseKey (hKey); 
//设置 ODBC数据库引擎名称 

lReturn=::RegOpenKeyEx (HKEY_LOCAL_MACHINE, " SOFTWARE\\ODBC\\ODBC.INI\\ODBC Data Sources" ,0L,KEY_WRITE,& hKey); 

if(lReturn !=ERROR_SUCCESS) 

return false; 

CString strDbType=" Microsoft Access Driver (* .mdb)" ; ::RegSetValueEx (hKey,strSourceName,0L,REG_SZ,(CONST BYTE* )((LCTSTR)strDbType),strDbType.GetLength ()); 

return true; 



  由于在动态加载中,一般只会改变数据库文件、数据源说明以及数据源描述,故上述函数可以实现应用中的大部分要求。如果应用中还需要作更多的改变,那么也可以通过改变函数参数的方式加以实现。对于需要动态加载多种类型数据源的情况,可以用具有不同参数的重载函数去实现。 

  方法二:利用 DLL 

  设计思路 

  Windows系统子目录中的动态链接库 Odbcinst.dll提供了一个可以动态地增加、修改和删除数据源的函数 SQLConfigDataSource()。该函数的原型如下: 

  BOOL SQLConfigDataSource(HWND hwndParent,WORD fRequest, LPCSTR lpszDriver, LPCSTR lpszAttributes); 

hwndParent参数是父窗口句柄。如果该值为 NULL,将不会显示与父窗口有关的对话框。 

fRequest参数可以设置为下面的数值之一: 

阅读(372) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~