方法一:修改注册表
设计思路
一般情况下,当用户在控制面板中配置好 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[]=\" file://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; [Page]
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+ =\" file://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 ());