我想在DLL中建立对话框并使用ADO访问数据库来输入数据,但是发现在DLL中无法创建有效的ADO指针。以最小代码进行了测试也还是如此,所以上来发帖求教。以下是DLL的最小测试代码!另外在DLL中使用ADO需要使用命名空间,不知为什么。如上:
#pragma  warning(disable:4146)  
#import  "C:\Program Files\Common Files\System\ado\msado15.dll"  named_guids  rename("EOF","adoEOF")  
#pragma  warning(default:4146)  
using  namespace  ADODB;
/////////////////////////////////////////////////////////////////
我使用的是常规MFC DLL,输出函数,在DLL访问这个函数来运行对话框。代码如下:
class Runmyado
{
public:
_ConnectionPtr m_pConnection;
BOOL RunOpen ()
{
HRESULT t_hr;
try
{
t_hr = m_pConnection.CreateInstance("ADODB.Connection");///创建Connection对象

// 打开本地Access库Demo.mdb 
if(SUCCEEDED(t_hr))
{
m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Count.mdb","","",adModeUnknown); 
}
else
{
return FALSE;
}

catch(_com_error e) 

CString errormessage;
errormessage.Format((_T("连接数据库失败!\r\n错误信息:%s")),e.ErrorMessage());
AfxMessageBox(errormessage);///显示错误信息
//DestroyWindow ();
return FALSE;
}
return TRUE;
}
};extern "C" BOOL _declspec(dllexport) GoAdo ()
{
Runmyado t_myado;
if (t_myado.RunOpen ())
{
AfxMessageBox ("程序正常运行!");
return TRUE;
}
return FALSE;

}

解决方案 »

  1.   

    先调用 CoInitialize()结束调用 CoUninitialize()
      

  2.   

    1.stdafx.h中加入
    #import "C:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename("EOF","adoEOF") 
    2。app文件的InitInstance中加入
    if(S_OK!=OleInitialize(NULL))  //或者CoInitialize()
    {
    AfxMessageBox("初始化COM组件库错误");
    }
    下面就是数据库操作
    _ConnectionPtr pConn;
    _RecordsetPtr  pRs;
    CString strSQL;
    pConn.CreateInstance(__uuidof(Connection));
    pConn->CursorLocation=adUseClient;
    strSQL="Provider=SQLOLEDB;Server=Gooyan;DataBase=SkillsBox;UID=sa;PWD=aaaaaaaa";
    pConn->Open(_bstr_t(strSQL),"","",-1);pRs.CreateInstance(__uuidof(Recordset));
    pRs->CursorLocation=adUseClient;
    pRs->PutActiveConnection(pConn.GetInterfacePtr());pRs1.CreateInstance(__uuidof(Recordset));
    pRs1->CursorLocation=adUseClient;
    pRs1->PutActiveConnection(pConn.GetInterfacePtr());strSQL="select * from catalog order by cataid";
    pRs->Open(_bstr_t(strSQL),vtMissing,adOpenDynamic,adLockBatchOptimistic,adCmdText);
      

  3.   

    在 CreateInstance 之前必须 CoInitialize(NULL);
    在 PROCESS_DETACH 之前 CoUninitialize();
      

  4.   

    加了OleInitialize就可以了,可是为什么呢。我有用AfxOleInit进行初始化,两者有什么不同吗?
      

  5.   

    AfxOleInit 中有这么一句话 // Special case DLL context to assume that the calling app initializes OLE.
    // For DLLs where this is not the case, those DLLs will need to initialize
    // OLE for themselves via OleInitialize.  This is done since MFC cannot provide
    // automatic uninitialize for DLLs because it is not valid to shutdown OLE
    // during a DLL_PROCESS_DETACH.
    if (afxContextIsDLL)
    {
    pState->m_bNeedTerm = -1;  // -1 is a special flag
    return TRUE;
    }
      

  6.   

    所以 AfxOleInit 就是不对 DLL 起作用
      

  7.   

    可奇怪的时,当我把AfxOleInit ()放在DLL中CreateInstance之前就可以了。之前之所以出问题,就因为我把AfxOleInit ()放到MFC DLL的InitInstance中了。
      

  8.   

    是放在 InitInstance 之前吧
    因为 MFC 中的实现是
    BOOL AFXAPI AfxOleInit()
    {
    _AFX_THREAD_STATE* pState = AfxGetThreadState();
    ASSERT(!pState->m_bNeedTerm);    // calling it twice? if (afxContextIsDLL)
    {
    pState->m_bNeedTerm = -1;  // -1 is a special flag
    return TRUE;
    }
    而 afxContextIsDLL 的定义是 #define afxContextIsDLL AfxGetModuleState()->m_bDLL
    大概此时的 m_bDLL 为 FALSE 吧,但这样使用可能会有一些不安全的因素
      

  9.   

    CoInitialize()
     CoUninitialize()
      

  10.   

    CoInitialize和 CoUninitialize最好不要放在DLL的InitInstance和ExitInstance因为调用的时间不确定, 如果一个Dll里CoInitialize,另一个CoUninitialize了,会造成一些错误