關鍵點:連接字符串中添加 Jet OLEDB:Database Password=xxx
CString GetConnStr(LPCTSTR dbPath, LPCTSTR pwd) {
CString str;
str.Format(_T("Provider=Microsoft.Jet.OLEDB.4.0;"
"Data Source=%s;"
"Persist Security Info=False;"
"Jet OLEDB:Database Password=%s;"),
dbPath, pwd);
return str;
}
Persist Security Info=False:防止密碼在連接對象屬性中被讀取。Jet OLEDB:Database Password:Jet 4.0 專用密碼參數。ACE 12.0 (.accdb) 同樣支持。
#include // 若用 ATL OLE DB Consumer
// 或 #import msado15.dll 配合下列代碼
void QueryPasswordDB() {
::CoInitialize(NULL);
_ConnectionPtr pConn;
_RecordsetPtr pRs;
CString dbPath, pwd = _T("cd"); // 密碼
// 獲取數據庫路徑(同目錄下 pass.mdb)
TCHAR szPath[MAX_PATH];
GetModuleFileName(NULL, szPath, MAX_PATH);
PathRemoveFileSpec(szPath);
dbPath.Format(_T("%s\\pass.mdb"), szPath);
try {
pConn.CreateInstance(__uuidof(Connection));
pRs.CreateInstance(__uuidof(Recordset));
CString connStr = GetConnStr(dbPath, pwd);
pConn->Open((_bstr_t)connStr, "", "", adModeUnknown);
CString sql = _T("SELECT pass FROM PassTable");
pRs->Open((_variant_t)sql, pConn.GetInterfacePtr(),
adOpenDynamic, adLockOptimistic, adCmdText);
while (!pRs->adoEOF) {
_variant_t val = pRs->GetCollect(_T("pass"));
if (val.vt != VT_NULL) {
CString pass = (LPCTSTR)(_bstr_t)val;
AfxMessageBox(_T("讀取密碼: ") + pass);
}
pRs->MoveNext();
}
}
catch (_com_error &e) {
CString msg;
msg.Format(_T("ADO 錯誤: %s"), e.ErrorMessage());
AfxMessageBox(msg);
}
if (pRs->State) pRs->Close();
if (pConn->State) pConn->Close();
::CoUninitialize();
}
| 代碼 | 作用 |
|---|---|
pConn.GetInterfacePtr() | 獲取底層 IDispatch* 傳給 Recordset::Open 的 ActiveConnection 參數 |
(_variant_t)sql | 將 CString 隱式轉換為 VARIANT (VT_BSTR) |
(_bstr_t)connStr | 轉為 BSTR 供 Connection::Open 使用 |
pRs->GetCollect("pass") | 按字段名獲取值,返回 _variant_t,支持 NULL |
(LPCTSTR)(_bstr_t)val | 雙重轉換:_variant_t→_bstr_t→LPCTSTR,安全處理 NULL |
0x80040E4D (DB_E_NOTAUTHORIZED) → 檢查大小寫、特殊字符轉義。Project → Platform Target 必須一致。Mode=Read|Share Deny None。此模式適用於桌面應用內嵌加密 Access 數據庫,部署簡單(單文件)、安全性足夠(AES 加密、密碼保護)。