部署使用 ODBC 的應用程式時,手動在「控制台 -> 系統管理工具 -> ODBC 資料來源」建立 DSN 既繁瑣又易出錯。本文展示如何使用 ODBC API SQLConfigDataSource 在安裝程式或首次運行時代碼自動建立/修改/刪除 User DSN 與 System DSN,支援 Access、SQL Server、Oracle,含通用封裝函數。
BOOL SQLConfigDataSource(
HWND hwndParent, // 父視窗 (NULL=無對話框)
WORD fRequest, // 操作類型
LPCSTR lpszDriver, // 驅動程式描述字串
LPCSTR lpszAttributes // 屬性字串 (關鍵)
);
| 常數 | 值 | 說明 |
|---|---|---|
| ODBC_ADD_DSN | 1 | 新增 User DSN |
| ODBC_CONFIG_DSN | 2 | 修改 User DSN |
| ODBC_REMOVE_DSN | 3 | 刪除 User DSN |
| ODBC_ADD_SYS_DSN | 4 | 新增 System DSN (需管理員) |
| ODBC_CONFIG_SYS_DSN | 5 | 修改 System DSN |
| ODBC_REMOVE_SYS_DSN | 6 | 刪除 System DSN |
"Microsoft Access Driver (*.mdb)" (或 "Microsoft Access Driver (*.mdb, *.accdb)" ACE)"SQL Server" (或 "ODBC Driver 17 for SQL Server")"Oracle in OraClient11g_home1" (視安裝家目錄而定)關鍵字=值 以 雙 Null 結尾 (即 Key1=Val1\0Key2=Val2\0\0)。
"DSN=MyDSN\0DBQ=C:\\Data\\db.mdb\0DefaultDir=C:\\Data\0\0""DSN=MyDSN\0SERVER=192.168.1.100\0DATABASE=MyDB\0\0""DSN=MyDSN\0SERVER=ORCL\0UID=scott\0\0"代碼中常用技巧: 用 ! 佔位雙 Null,最後 strchr 替換為 \0。
// 返回: 1/2/3 成功 (Access/SQL/Oracle), -1/-2/-3 失敗, -4 不支援類型
int CreateDSN(CString strDSN, CString strDBPath, CString strDesc,
CString strServer, CString strUID, int dbType) {
// dbType: 1=Access, 2=SQL Server, 3=Oracle
char attr[512] = {0};
switch (dbType) {
case 1: // Access
sprintf(attr, "DSN=%s!DESCRIPTION=%s!DBQ=%s!FIL=MS Access!DEFAULTDIR=%s!!",
strDSN, strDesc, strDBPath, strDBPath); // 簡化目錄
break;
case 2: // SQL Server
sprintf(attr, "DSN=%s!DESCRIPTION=%s!SERVER=%s!DATABASE=%s!!",
strDSN, strDesc, strServer, strDBPath); // strDBPath 當 Database 名
break;
case 3: // Oracle
sprintf(attr, "DSN=%s!DESCRIPTION=%s!SERVER=%s!UID=%s!!",
strDSN, strDesc, strServer, strUID);
break;
default: return -4;
}
// 將 ! 替換為 \0
for (char* p = attr; *p; ++p) if (*p == '!') *p = '\0';
// 雙結尾已由 memset 0 保證
const char* driver = (dbType==1) ? "Microsoft Access Driver (*.mdb)" :
(dbType==2) ? "SQL Server" : "Oracle in OraClient11g_home1";
WORD req = ODBC_ADD_SYS_DSN; // 建議建 System DSN, 全用戶可見
if (!SQLConfigDataSource(NULL, req, driver, attr)) {
DWORD err = SQLInstallerError(); // 取得安裝器錯誤碼
TRACE("SQLConfigDataSource failed: %d\n", err);
return -(dbType);
}
return dbType;
}
#include (標頭檔)。odbccp32.lib (VC 目錄 lib 下),Project Settings -> Link -> Object/Library modules 加入 odbccp32.lib。CString GetAppDir() {
CString path; GetModuleFileName(NULL, path.GetBuffer(MAX_PATH), MAX_PATH); path.ReleaseBuffer();
int pos = path.ReverseFind('\\'); return path.Left(pos);
}
CString dbFile = GetAppDir() + _T("\\data.mdb");
CreateDSN(_T("MyAppDSN"), dbFile, _T("MyApp Database"), _T(""), _T(""), 1);
HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\ (User) / HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI\ (System)。此技術是專業安裝包 (InstallShield/NSIS/Inno Setup) 或自更新程式的標準配置步驟。