You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 07:45:29