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[]=\" 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 ());

 

::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;

}

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

  方法二:利用 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编辑框中增加 odbc32.lib,同时保证系统目录 system32下有文件 odbccp32.dll。

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

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

  小结

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

时间: 2024-08-03 07:14:58

VC中动态加载ODBC解决方法的相关文章

flash as3 中动态加载库类失败解决方法

flash as3 中动态加载库类失败解决方法 这是错误的写法 for (var i:number=1; i<4; i++) { var mc1:mc1 = new mc1(); addchild(mc1); } as3里怎么循环加载库里的mc1 mc2 mc3类 就是下面意思是怎样个的写法 for (var i:number=1; i<4; i++) { var "mc"+i:"mc"+i = new "mc"+i(); addch

Android开发中Listview动态加载数据的方法示例

本文实例讲述了Android开发中Listview动态加载数据的方法.分享给大家供大家参考,具体如下: 最近在研究网络数据加载的问题,比如我有几百,甚至上千条数据,这些数据如果一次性全部加载到arraylist,然后再加载到Listview中.我们必然会去单独开线程来做,这样造成的结果就是会出现等待时间很长,用户体验非常不好.我的想法是动态加载数据,第一次加载十条,然后往下面滑动的时候再追加十条,再往下面滑动的时候再去追加,这样大大减少了用户等待的时间,同时给处理数据留下了时间.网上看到了这样一

从XML中动态加载菜单的示例

本文配套源码 这个案例是一个基于VS2005的WinForm菜单控件的例子,功能是从XML中动态加载菜单数据到MenuTrip控件上.这个案例中用到了XML,反射之类的技术.当然实用价值有限,仅供学习参考之用. 首先创建一个WinForm项目,在Form1上放置一个MenuTrip控件,将其命名为MainMenu. 在项目中添加一个XML文件,命名为Menu.xml,代码如下: MenuXml 1<?xml version="1.0" encoding="utf-8&q

python中动态加载模块和类方法实现

python中动态加载模块和类方法实现测试代码   文件名: mytest.py 具体代码如下:   注意:模块名,类名,方法名都是变量.   #coding=UTF-8 class TestClass: def sub(self,a,b): return a-b def add(self,a,b): return a+b def echo(self): print "test" def main(): class_name = "TestClass" #类名 mo

DataTables+BootStrap组合使用Ajax来获取数据并且动态加载dom的方法(排序,过滤,分页等)_jquery

Datatables是一款jquery表格插件.它是一个高度灵活的工具,可以将任何HTML表格添加高级的交互功能. 主要功能 分页,即时搜索和排序 几乎支持任何数据源:DOM, javascript, Ajax 和 服务器处理 支持不同主题 DataTables, jQuery UI, Bootstrap, Foundation 各式各样的扩展: Editor, TableTools, FixedColumns -- 丰富多样的option和强大的API 支持国际化 超过2900+个单元测试 免

动态加载js的方法汇总_javascript技巧

本文实例汇总了动态加载js的方法.分享给大家供大家参考.具体如下: 方法一:直接document.write(异步) 复制代码 代码如下: <script language="javascript">       document.write("<script src='res/extwidget/echarts/xx.js'><\/script>"); </script> 由于这种方式是异步加载,document.w

flex4/flash builder中动态加载Module并与之交互的正确方式

关于flex中动态加载Module的文章,网上有很多,但多半是基于flex3的,如果在flash builder/flex4中按他们所提供的方法去做,最后将module加载到容器中时,会报:null object reference错误. 经过多番摸索,发现只能在ready回调中,以Object这种基本类型使用,不能强制做任何类型转型,方能正常加载到容器,并与加载后的实例交互(虽然这样flash builder的IDE环境中,无法智能代码提示),原因不明! 开始吧,先创建一个mxml Modul

在MVC应用程序中动态加载PartialView

原文:在MVC应用程序中动态加载PartialView 有时候,我们不太想把PartialView直接Render在Html上,而是使用jQuery来动态加载,或是某一个事件来加载. 为了演示与做好这个练习,我们先在Views目录下的Home下创建_Partial1.cshtml部分视图,视图内容任你自定义,Insus.NET在本例中只让其显示一些文字与一张图片: 接下来,我们需要建立一个ActionResult()方法,在Controllers目录之下,打开HomeController.cs:

Visual Basic .NET 中动态加载类(一)

visual|动态|加载 Visual Basic .NET 中动态加载类 · ··Microsoft 摘要:理想情况下,编写软件系统之前我们就应该知道此软件系统需要完成哪些操作.但实际情况并非如此,因此我们的系统应该是可以调整的. 最能体现这种适应性的是动态集成新功能的能力.例如,在 Windows 窗体应用程序中,这种能力是指加载编译原始应用绦蚝芫靡院蟠唇ǖ拇疤宓哪芰Α?/P> 这种操作在 Microsoft Visual Basic 6.0 中几乎是不可能的,但是在 Visual Basi