在VC中动态加载ODBC的方法
生活随笔
收集整理的這篇文章主要介紹了
在VC中动态加载ODBC的方法
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
| 在VC中動(dòng)態(tài)加載ODBC的方法 |
| ????在使用VC、VB、Delphi等高級(jí)語(yǔ)言編寫數(shù)據(jù)庫(kù)應(yīng)用程序時(shí),往往需要用戶自己在控制面板中配置ODBC數(shù)據(jù)源。對(duì)于一般用戶而言,配置ODBC數(shù)據(jù)源可能是一件比較困難的工作。而且,在實(shí)際應(yīng)用中,用戶往往要求在同一個(gè)應(yīng)用程序中訪問(wèn)不同的數(shù)據(jù)源,因此采用一般的加載方法就有了無(wú)法克服的缺陷。為能在程序中完成這一工作,方便應(yīng)用程序的使用,本文以VC為開(kāi)發(fā)環(huán)境介紹兩種在應(yīng)用程序中動(dòng)態(tài)加載ODBC系統(tǒng)數(shù)據(jù)源的方法。 方法一:修改注冊(cè)表 設(shè)計(jì)思路 ????一般情況下,當(dāng)用戶在控制面板中配置好ODBC數(shù)據(jù)源后,Windows系統(tǒng)便在注冊(cè)表中加入了一些子鍵來(lái)存儲(chǔ)用戶的配置結(jié)果。當(dāng)應(yīng)用程序需要用到數(shù)據(jù)源時(shí),Windows便會(huì)通知底層接口查閱注冊(cè)表中該數(shù)據(jù)源的配置。如果用戶刪除了某個(gè)ODBC數(shù)據(jù)源,那么也會(huì)在注冊(cè)表中有所反應(yīng)。如果配置的數(shù)據(jù)源是用戶數(shù)據(jù)源,?Windows系統(tǒng)便會(huì)修改注冊(cè)表的HKEY_CURRENT_USER/SOFTWARE/ODBC/ODBC.INI子鍵;如果配置的數(shù)據(jù)源是系統(tǒng)數(shù)據(jù)源,Windows系統(tǒng)便會(huì)修改注冊(cè)表的HKEY_LOCAL_MACHINE/SOFTWARE/ODBC/ODBC.INI主鍵。因此,我們可以在應(yīng)用程序中使用Windows?API中的注冊(cè)表編輯函數(shù)來(lái)完成Windows所做的工作,這樣就可以達(dá)到動(dòng)態(tài)加載數(shù)據(jù)源的目的。 具體實(shí)現(xiàn) ????對(duì)于不同類型的數(shù)據(jù)源,注冊(cè)表的修改也各有不同,但基本上都要修改兩個(gè)地方。一個(gè)是在?ODBC.INI子鍵下建立一個(gè)與數(shù)據(jù)源描述名同名的子鍵,并在該子鍵下建立與數(shù)據(jù)源配置相關(guān)的項(xiàng);另一個(gè)是在ODBC.INI/ODBC?Data?Sources子鍵下建立一個(gè)新項(xiàng)以便告訴驅(qū)動(dòng)程序管理器ODBC數(shù)據(jù)源的類型。下面以配置一個(gè)Microsoft?Access數(shù)據(jù)源為例給出實(shí)現(xiàn)此功能的函數(shù)的代碼。 /*strSourceName是要?jiǎng)?chuàng)建的數(shù)據(jù)源名,strSourceDb是數(shù)據(jù)庫(kù)存放路徑,strDescription是數(shù)據(jù)源的描述字符串。*/ BOOL?CLoadOdbcDlg::LoadDbSource(CString?strSourceName,?CString?strSourceDb,?CString?strDescription) { ??//存放打開(kāi)的注冊(cè)表鍵 ??HKEY?hKey; ??DWORD?dw; ??//存放注冊(cè)表API函數(shù)執(zhí)行的返回值 ??LONG?lReturn; ??//存放要打開(kāi)的子鍵 ??CString?strSubKey; ??//檢測(cè)是否安裝了MS?Access?ODBC?driver:odbcjt32.dll ??//獲得?Windows系統(tǒng)目錄 ??char?sysDir[MAX_PATH]; ??char?drvName[]="//odbcjt32.dll"; ??::GetSystemDirectory(sysDir,?MAX_PATH); ??strcat(sysDir,drvName); ??CFileFind?findFile; ??if(!findFile.FindFile(sysDir)) ??{ ????AfxMessageBox("您的計(jì)算機(jī)系統(tǒng)中沒(méi)有安裝MS?Access的ODBC驅(qū)動(dòng)程序odbcjt32.dll,您將無(wú)法加載該類數(shù)據(jù)源。"?,MB_OK?|?MB_ICONSTOP); ????return?false; ??} ??strSubKey="SOFTWARE//ODBC//ODBC.INI//"?+?strSourceName; ??//創(chuàng)建?ODBC數(shù)據(jù)源在注冊(cè)表中的子鍵 ??lReturn=::RegCreateKeyEx(HKEY_LOCAL_MACHINE,?(LPCTSTR)strSubKey,?0,?NULL,?REG_OPTION_NON_VOLATILE,KEY_WRITE,NULL,&hKey,&dw); ??if(lReturn?!=?ERROR_SUCCESS) ????return?false; ??//設(shè)置數(shù)據(jù)源的各項(xiàng)參數(shù) ??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); ??//創(chuàng)建?ODBC數(shù)據(jù)源的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; ??//設(shè)置該子鍵下的各項(xiàng)參數(shù) ??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); ??//設(shè)置ODBC數(shù)據(jù)庫(kù)引擎名稱 ??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; } 由于在動(dòng)態(tài)加載中,一般只會(huì)改變數(shù)據(jù)庫(kù)文件、數(shù)據(jù)源說(shuō)明以及數(shù)據(jù)源描述,故上述函數(shù)可以實(shí)現(xiàn)應(yīng)用中的大部分要求。如果應(yīng)用中還需要作更多的改變,那么也可以通過(guò)改變函數(shù)參數(shù)的方式加以實(shí)現(xiàn)。對(duì)于需要?jiǎng)討B(tài)加載多種類型數(shù)據(jù)源的情況,可以用具有不同參數(shù)的重載函數(shù)去實(shí)現(xiàn)。 方法二:利用DLL 設(shè)計(jì)思路 ????Windows系統(tǒng)子目錄中的動(dòng)態(tài)鏈接庫(kù)Odbcinst.dll提供了一個(gè)可以動(dòng)態(tài)地增加、修改和刪除數(shù)據(jù)源的函數(shù)SQLConfigDataSource()。該函數(shù)的原型如下: ????BOOL?SQLConfigDataSource(HWND?hwndParent,?WORD?fRequest,?LPCSTR?lpszDriver,?LPCSTR?lpszAttributes); hwndParent參數(shù)是父窗口句柄。如果該值為NULL,將不會(huì)顯示與父窗口有關(guān)的對(duì)話框。 fRequest參數(shù)可以設(shè)置為下面的數(shù)值之一: ??ODBC_ADD_DSN:增加一個(gè)新的用戶數(shù)據(jù)源; ODBC_CONFIG_DSN:修改(配置)一個(gè)已經(jīng)存在的用戶數(shù)據(jù)源; ODBC_REMOVE_DSN:刪除一個(gè)已經(jīng)存在的用戶數(shù)據(jù)源; ODBC_ADD_SYS_DSN:增加一個(gè)新的系統(tǒng)數(shù)據(jù)源; ODBC_CONFIG_SYS_DSN:修改?(配置)一個(gè)已經(jīng)存在的系統(tǒng)數(shù)據(jù)源; ODBC_REMOVE_SYS_DSN:刪除一個(gè)已經(jīng)存在的系統(tǒng)數(shù)據(jù)源。 ??lpszDriver參數(shù)用于傳遞數(shù)據(jù)庫(kù)引擎的名字,等同于方法一中strDbType變量。 ??lpszAttirbutes參數(shù)是關(guān)鍵字的值,即一連串的"keyname=value"字符串,每?jī)蓚€(gè)字符串之間用?"/"隔開(kāi),如?DSN?=?Personnel?Data/0UID=Smith/0DATABASE=Personnel。關(guān)于該參數(shù)的詳細(xì)設(shè)置請(qǐng)參閱MSDN中SQLConfigDataSource()函數(shù)的幫助文檔和各種ODBC驅(qū)動(dòng)程序文檔。 具體實(shí)現(xiàn) ????由于VC的缺省庫(kù)文件中不包含SQLConfigDataSource()函數(shù),因此使用該函數(shù)之前需要將odbcinst.h文件包含在工程的頭文件中,在工程的Settings屬性對(duì)話框Link屬性頁(yè)的Object/library?modules編輯框中增加odbccp32.lib,同時(shí)保證系統(tǒng)目錄system32下有文件odbccp32.dll。 ???仍以Microsoft?Access為例,設(shè)置數(shù)據(jù)源名為demo,數(shù)據(jù)源描述為"示例數(shù)據(jù)源",那么在需要?jiǎng)討B(tài)加載數(shù)據(jù)源的地方加入下列代碼即可: ? ????::SQLConfigDataSource(NULL,?ODBC_ADD_SYS_DSN,?"Microsoft?Access?Driver?(*.mdb)",?"DSN=demo/0Description=示例數(shù)據(jù)庫(kù)"); 小結(jié) ????上述兩種方法都可以實(shí)現(xiàn)動(dòng)態(tài)加載各種類型的ODBC數(shù)據(jù)源,并且在Windows95/98/NT/2000環(huán)境下調(diào)試通過(guò)。方法一在實(shí)現(xiàn)時(shí)需要較多的代碼,方法二所需代碼雖少,但需要額外文件的支持,而且隨著數(shù)據(jù)源配置的靈活性的增加,為了形成lpszAttributes字符串,其代碼長(zhǎng)度也會(huì)相應(yīng)增加。由于從控制面板配置數(shù)據(jù)源使得程序員可以獲得更加直觀的理解,所以對(duì)于注冊(cè)表中各項(xiàng)值以及相應(yīng)項(xiàng)名稱的獲得除了可以查閱相關(guān)驅(qū)動(dòng)程序的文檔外,程序員也可以在編程前先通過(guò)控制面板配置ODBC數(shù)據(jù)源,然后根據(jù)注冊(cè)表中相應(yīng)部分的內(nèi)容進(jìn)行編程。 |
總結(jié)
以上是生活随笔為你收集整理的在VC中动态加载ODBC的方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 入行AI,你需要一本Python机器学习
- 下一篇: 实验室服务器18.04LTS+RTX20