分享
 
 
 

在VC中动态加载ODBC的方法

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

在VC中动态加载ODBC的方法

在使用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, "ImplicitCommitSync", 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*)((LPCTSTR)strDbType), strDbType.GetLength());

return true;

}

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

方法二:利用DLL

设计思路

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

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

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

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

ODBC_ADD_DSN:增加一个新的用户数据源;

ODBC_CONFIG_DSN:修改(配置)一个已经存在的用户数据源;

ODBC_REMOVE_DSN:删除一个已经存在的用户数据源;

ODBC_ADD_SYS_DSN:增加一个新的系统数据源;

ODBC_CONFIG_SYS_DSN:修改 (配置)一个已经存在的系统数据源;

ODBC_REMOVE_SYS_DSN:删除一个已经存在的系统数据源。

lpszDriver参数用于传递数据库引擎的名字,等同于方法一中strDbType变量。

lpszAttirbutes参数是关键字的值,即一连串的"keyname=value"字符串,每两个字符串之间用 "\"隔开,如 DSN = Personnel Data\0UID=Smith\0DATABASE=Personnel。关于该参数的详细设置请参阅MSDN中SQLConfigDataSource()函数的帮助文档和各种ODBC驱动程序文档。

具体实现

由于VC的缺省库文件中不包含SQLConfigDataSource()函数,因此使用该函数之前需要将odbcinst.h文件包含在工程的头文件中,在工程的Settings属性对话框Link属性页的Object/library modules编辑框中增加odbccp32.lib,同时保证系统目录system32下有文件odbccp32.dll。

仍以Microsoft Access为例,设置数据源名为demo,数据源描述为"示例数据源",那么在需要动态加载数据源的地方加入下列代码即可:

::SQLConfigDataSource(NULL, ODBC_ADD_SYS_DSN, "Microsoft Access Driver (*.mdb)", "DSN=demo\0Description=示例数据库");

小结

上述两种方法都可以实现动态加载各种类型的ODBC数据源,并且在Windows95/98/NT/2000环境下调试通过。方法一在实现时需要较多的代码,方法二所需代码虽少,但需要额外文件的支持,而且随着数据源配置的灵活性的增加,为了形成lpszAttributes字符串,其代码长度也会相应增加。由于从控制面板配置数据源使得程序员可以获得更加直观的理解,所以对于注册表中各项值以及相应项名称的获得除了可以查阅相关驱动程序的文档外,程序员也可以在编程前先通过控制面板配置ODBC数据源,然后根据注册表中相应部分的内容进行编程。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有