在VC中动态加载ODBC的方法
生活随笔
收集整理的這篇文章主要介紹了
在VC中动态加载ODBC的方法
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
| 在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數據源,然后根據注冊表中相應部分的內容進行編程。 |
總結
以上是生活随笔為你收集整理的在VC中动态加载ODBC的方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 入行AI,你需要一本Python机器学习
- 下一篇: vc++学习精髓(收集,整理)