在非對話框類 (如 CDatabaseManager) 中宣告 _ConnectionPtr m_conn;、_RecordsetPtr m_rs;,呼叫 m_conn.CreateInstance(__uuidof(Connection)) 時拋出 _com_error 或 QueryInterface 失敗。
MFC 的 COleControl/CWnd 衍生類別在建構時期會初始化 COM 單元模型。若智慧指標 (_com_ptr_t) 作為**非視窗類別**的成員,其建構函式可能在 **COM 未初始化 (CoInitialize 未呼叫)** 或 **錯誤的 Apartment 狀態** 下執行,導致
BOOL CDatabaseManager::ExecuteSQL(CString sql) {
_ConnectionPtr conn; // 區域智慧指標,離開作用域自動 Release
HRESULT hr = conn.CreateInstance(__uuidof(Connection));
if (FAILED(hr)) return FALSE;
conn->Open(_bstr_t(connectionString), "", "", adConnectUnspecified);
conn->Execute(_bstr_t(sql), NULL, adCmdText);
return TRUE;
}
class CDatabaseManager {
_ConnectionPtr* m_pConn; // 指標,不自動建構
public:
CDatabaseManager() : m_pConn(nullptr) {}
~CDatabaseManager() { Close(); }
BOOL Open() {
if (m_pConn) return TRUE;
m_pConn = new _ConnectionPtr();
HRESULT hr = (*m_pConn)->CreateInstance(__uuidof(Connection));
if (FAILED(hr)) { delete m_pConn; m_pConn = nullptr; return FALSE; }
(*m_pConn)->Open(...);
return TRUE;
}
void Close() {
if (m_pConn) {
try { if ((*m_pConn)->State) (*m_pConn)->Close(); } catch(...) {}
delete m_pConn; m_pConn = nullptr;
}
}
};
class AdoConnection {
_ConnectionPtr conn;
public:
AdoConnection() = default;
~AdoConnection() { if (conn) try { conn->Close(); } catch(...) {} }
BOOL Open(LPCTSTR connStr) {
HRESULT hr = conn.CreateInstance(__uuidof(Connection));
if (FAILED(hr)) return FALSE;
conn->Open(_bstr_t(connStr), "", "", adConnectUnspecified);
return TRUE;
}
operator _ConnectionPtr&() { return conn; }
_ConnectionPtr* operator&() { return &conn; }
};
// 使用
class CDatabaseManager {
AdoConnection m_conn; // 成員變數安全
public:
BOOL Execute(LPCTSTR sql) {
if (!m_conn) m_conn.Open(connStr); // 延遲開啟
m_conn->Execute(_bstr_t(sql), NULL, adCmdText);
return TRUE;
}
};
MFC 非對話框類中**不要直接宣告 _ConnectionPtr/_RecordsetPtr 成員**。改用區域變數、指標延遲建構或 RAII 包裝,確保 COM 操作在 CoInitialize 之後、正確 Apartment 執行緒中進行。