使用CDatabase打开ACCDB文件弹出选择数据源窗口的问题
Access 2021 x64环境下CDatabase连接弹出数据源选择窗口的原因
问题背景
我开发的64位软件使用CDatabase对象连接Access数据库,在安装Office 365 x64的开发机上运行正常,但在安装Access 2021 x64的用户电脑上,调用CDatabase::OpenEx时会意外弹出选择数据源窗口(即使代码中指定了CDatabase::noOdbcDialog参数)。
连接字符串的生成逻辑并非硬编码驱动名称,而是通过遍历系统安装的JET驱动获取,核心代码如下:
连接代码片段
CString strDBConnectString = L"Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=<path to db>;Pwd="; m_Database.OpenEx(strDBConnectString, CDatabase::noOdbcDialog)
驱动遍历代码
// 遍历JET驱动列表,查找有效的MDB驱动 CString CCommunityTalksApp::GetJETDriverEx(bool bAccDbMode) { CString strDriver; CString strName, strNameLower, strValue; CString strDefaultDriver = _T("Microsoft Access Driver (*.mdb)"); CString strDBType = _T("(*.mdb)"); CStringArray aryStrDrivers; TCHAR szBuf[2001]{}; WORD cbBufMax = 2000; WORD cbBufOut; TCHAR* pszBuf = szBuf; if (SQLGetInstalledDrivers(szBuf, cbBufMax, &cbBufOut)) { #ifdef _WIN64 strDefaultDriver = _T("Microsoft Access Driver (*.mdb, *.accdb)"); strDBType = _T("(*.mdb, *.accdb)"); #else if (bAccDbMode) { strDefaultDriver = _T("Microsoft Access Driver (*.mdb, *.accdb)"); strDBType = _T("(*.mdb, *.accdb)"); } #endif while (*pszBuf) { strName = CString(pszBuf); strNameLower = strName; strNameLower.MakeLower(); if (strNameLower.Find(strDBType) != -1) { aryStrDrivers.Add(strName); if (strName.CollateNoCase(strDefaultDriver) == 0) { strDriver = strName; break; } } pszBuf += strName.GetLength() + 1; } if (strDriver.IsEmpty() && aryStrDrivers.GetSize() > 0) { // 使用找到的第一个MDB驱动 strDriver = aryStrDrivers.GetAt(0); } } // 记录驱动名称 AfxGetApp()->WriteProfileString(_T("Options"), _T("JET Connection Driver"), strDriver); return strDriver; }
底层原因分析
1. 驱动名称匹配失败
Access 2021 x64的ODBC驱动名称和Office 365 x64存在差异:
- Office 365的驱动名称为
Microsoft Access Driver (*.mdb, *.accdb) - Access 2021的驱动名称扩展为
Microsoft Access Driver (*.mdb, *.accdb, *.accdt, *.accde, *.accdr)
你的代码中64位环境下硬指定strDBType为(*.mdb, *.accdb),导致遍历驱动时,Access 2021的驱动名称无法被匹配到(因为其包含更多文件类型后缀),最终strDriver为空。
2. 空驱动触发ODBC fallback逻辑
当GetJETDriverEx返回空字符串时,连接字符串中的Driver={}部分无效,ODBC管理器无法定位到可用驱动。此时即使设置了CDatabase::noOdbcDialog,系统仍会弹出数据源选择窗口——这是ODBC的 fallback 机制,试图让用户手动指定有效数据源来完成连接。
3. 缓冲区大小不足导致驱动列表截断
代码中szBuf仅分配了2000字节,如果用户系统中安装的ODBC驱动较多,或者驱动名称较长,SQLGetInstalledDrivers返回的驱动列表可能被截断,Access 2021的驱动信息未被完整读取,自然无法被匹配到。
内容的提问来源于stack exchange,提问作者Andrew Truckle
相关产品推荐
相关产品推荐

