我在一个COM的接口函数中返回一个类,应用程序调用此COM接口如何获取此返回的类?直接在接口参数中将返回值定义成我要返回的类编译不会通过,我是用IDispatch将此类返回的,但是在应用程序调用时此接口返回IDispatch**,再转换为我要的类时没有出错,但是在调用这个类的方法时出现异常。
COM接口的代码是:
[id(22), helpstring("设计DTS包类的属性")] HRESULT GetDTSPackage2([out, retval]IDispatch **pPackage2);STDMETHODIMP CDTSPackage2::GetDTSPackage2(IDispatch **pPackage2)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState()) CoInitialize(NULL);
_Package2 objPackage2;
if (!objPackage2.CreateDispatch("DTS.Package2"))
{
m_dwErrorNumber = ERROR_PACKAGE2CREATEDISPATCH;
*pPackage2 = NULL;
return S_OK;
} try
{
objPackage2.SetName(m_dtsPackage2.szPackageName);
objPackage2.SetWriteCompletionStatusToNTEventLog(m_dtsPackage2.bWriteCompletionStatusToNTEventLog);
objPackage2.SetFailOnError(m_dtsPackage2.bFailOnError);
objPackage2.SetPackagePriorityClass(m_dtsPackage2.lPackagePriorityClass);
objPackage2.SetMaxConcurrentSteps(m_dtsPackage2.lMaxConcurrentSteps);
objPackage2.SetLineageOptions(m_dtsPackage2.lLineageOptions);
objPackage2.SetUseTransaction(m_dtsPackage2.bUseTransaction);
objPackage2.SetTransactionIsolationLevel(m_dtsPackage2.lTransactionIsolationLevel);
objPackage2.SetAutoCommitTransaction(m_dtsPackage2.bAutoCommitTransaction);
objPackage2.SetRepositoryMetadataOptions(m_dtsPackage2.lRepositoryMetadataOptions);
objPackage2.SetUseOLEDBServiceComponents(m_dtsPackage2.bUseOLEDBServiceComponents);
objPackage2.SetLogToSQLServer(m_dtsPackage2.bLogToSQLServer);
objPackage2.SetLogServerFlags(m_dtsPackage2.lLogServerFlags);
objPackage2.SetFailPackageOnLogFailure(m_dtsPackage2.bFailPackageOnLogFailure);
objPackage2.SetExplicitGlobalVariables(m_dtsPackage2.bExplicitGlobalVariables);
objPackage2.SetPackageType(m_dtsPackage2.lPackageType);
////////////////////
objPackage2.SetDescription(m_dtsPackage2.szDescription);
objPackage2.SetLogFileName(m_dtsPackage2.szLogFileName);
objPackage2.SetLogServerName(m_dtsPackage2.szLogServerName);
objPackage2.SetLogServerPassword(m_dtsPackage2.szLogServerPassword);
objPackage2.SetLogServerUserName(m_dtsPackage2.szLogServerPassword);
}
catch (_com_error &e)
{
*pPackage2 = NULL;
PrintComError(e);
m_dwErrorNumber = ERROR_PACKAGE2CREATEDISPATCH;
return S_OK;
} m_dwErrorNumber = 0;
*pPackage2 = objPackage2;
memset(&m_dtsPackage2, 0, sizeof(m_dtsPackage2));
return S_OK;
}

解决方案 »

  1.   

    应用程序代码是:
    void CTestWorkformSystemDlg::OnBtndtsinterface() 
    {
    CoInitialize(NULL);
    IDTSPackage2 *pPack = NULL;
    IDTSConnection2 *pConn1 = NULL;
    IDTSConnection2 *pConn2 = NULL;
    IDTSStep *pStep = NULL;
    IDTSDataPumpTask *pTask = NULL;
    IDTSOleDBProperty2 *pProp2 = NULL;
    IDTSTransformation2 *pTran = NULL;
    IDTSColumn *pCol1 = NULL;
    IDTSColumn *pCol2 = NULL;

    HRESULT ret = CoCreateInstance(
    CLSID_DTSPackage2,
    NULL,
    CLSCTX_ALL,
    IID_IDTSPackage2,
    (LPVOID *)&pPack
    ); ret = CoCreateInstance(
    CLSID_DTSConnection2,
    NULL,
    CLSCTX_ALL,
    IID_IDTSConnection2,
    (LPVOID *)&pConn1
    ); ret = CoCreateInstance(
    CLSID_DTSConnection2,
    NULL,
    CLSCTX_ALL,
    IID_IDTSConnection2,
    (LPVOID *)&pConn2
    ); ret = CoCreateInstance(
    CLSID_DTSStep,
    NULL,
    CLSCTX_ALL,
    IID_IDTSStep,
    (LPVOID *)&pStep
    ); ret = CoCreateInstance(
    CLSID_DTSDataPumpTask,
    NULL,
    CLSCTX_ALL,
    IID_IDTSDataPumpTask,
    (LPVOID *)&pTask
    ); ret = CoCreateInstance(
    CLSID_DTSOleDBProperty2,
    NULL,
    CLSCTX_ALL,
    IID_IDTSOleDBProperty2,
    (LPVOID *)&pProp2
    ); ret = CoCreateInstance(
    CLSID_DTSTransformation2,
    NULL,
    CLSCTX_ALL,
    IID_IDTSTransformation2,
    (LPVOID *)&pTran
    ); ret = CoCreateInstance(
    CLSID_DTSColumn,
    NULL,
    CLSCTX_ALL,
    IID_IDTSColumn,
    (LPVOID *)&pCol1
    ); ret = CoCreateInstance(
    CLSID_DTSColumn,
    NULL,
    CLSCTX_ALL,
    IID_IDTSColumn,
    (LPVOID *)&pCol2
    );

    pPack->put_bAutoCommitTransaction(TRUE);
    pPack->put_bExplicitGlobalVariables(TRUE);
    pPack->put_bFailOnError(TRUE);
    pPack->put_bFailPackageOnLogFailure(TRUE);
    pPack->put_bLogToSQLServer(FALSE);
    pPack->put_bUseOLEDBServiceComponents(TRUE);
    pPack->put_bUseTransaction(TRUE);
    pPack->put_bWriteCompletionStatusToNTEventLog(FALSE);
    pPack->put_lLineageOptions(0);
    pPack->put_lLogServerFlags(0);
    pPack->put_lMaxConcurrentSteps(4);
    pPack->put_lPackagePriorityClass(2);
    pPack->put_lPackageType(0);
    pPack->put_lRepositoryMetadataOptions(0);
    pPack->put_lTransactionIsolationLevel(4096);
    pPack->put_szDescription(L"向远程服务器导数据");
    pPack->put_szLogFileName(L"c:\\logfile.txt");
    pPack->put_szLogServerName(L"");
    pPack->put_szLogServerPassword(L"");
    pPack->put_szLogServerUserName(L"");
    pPack->put_szPackageName(L"批量数据导入");
    IDispatch* obj = NULL;
    pPack->GetDTSPackage2(&obj);
    _Package2 objpak2;
    // BOOL bRet = objpak2.CreateDispatch("DTS.Package2");
    objpak2.AttachDispatch(obj);
    CString str = objpak2.GetDescription();        //这句出错
    // objpak2.m_lpDispatch = obj; Connections objConns(objpak2.GetConnections());    //这句出错
    Connection2* objConn1 = NULL; pProp2->put_lColumnLengths(11);
    pProp2->put_lFileFormat(1);
    pProp2->put_lFileType(1);
    pProp2->put_lMaxCharactersPerDelimitedColumn(255);
    pProp2->put_lMode(1);
    pProp2->put_lSkipRows(0);
    pProp2->put_lNumberofColumn(1);
    pProp2->put_szColumnDelimiter(L"|");
    pProp2->put_szDataSource(L"c:\\bbb.txt");
    pProp2->put_szRowDelimiter(L"\r\n");
    pProp2->put_szTextQualifier(L"\"");
    pProp2->put_bFirstRowColumnName(FALSE); pConn1->put_lConnectionId(1);
    pConn1->put_bReusable(TRUE);
    pConn1->put_szConnectionName(L"TextFile");
    pConn1->put_bUseDSL(FALSE);
    pConn1->put_bConnectImmediate(FALSE);
    pConn1->put_lConnectionTimeout(60);
    pConn1->put_bUseTrustedConnection(FALSE);
    pConn1->put_szDataSource(L"c:\\bbb.txt"); pPack->GetDTSFlatFileConnection2(pProp2, pConn1, (IDispatch *)&objConns, &obj);
    // objConn1 = (Connection2 *)obj;
    objConns.Add(obj); Connection2* objConn2 = NULL;
    pConn2->put_lConnectionId(2);
    pConn2->put_bReusable(TRUE);
    pConn2->put_szConnectionName(L"pubcon");
    pConn2->put_bUseDSL(FALSE);
    pConn2->put_bConnectImmediate(FALSE);
    pConn2->put_lConnectionTimeout(60);
    pConn2->put_bUseTrustedConnection(FALSE);
    pConn2->put_szDataSource(L"TRASIN-GUOYONG");
    pConn2->put_szCatalog(L"pubs");
    pConn2->put_szUserID(L"sa");
    pConn2->put_szPassword(L"gisterguoyong");
    pPack->GetSQLOLEDBConnection2((IDispatch *)&objConns, pConn2, &obj);
    // objConn2 = (Connection2 *)obj;
    objConns.Add(obj);
    Steps objSteps(objpak2.GetSteps());
    pStep->put_bAddGlobalVariables(TRUE);
    pStep->put_bCloseConnection(TRUE);
    pStep->put_bCommitSuccess(FALSE);
    pStep->put_bDisableStep(FALSE);
    pStep->put_bExecuteInMainThread(TRUE);
    pStep->put_bFailPackageOnError(FALSE);
    pStep->put_bIsPackageDSORowset(FALSE);
    pStep->put_bJoinTransactionIfPresent(FALSE);
    pStep->put_bRollbackFailure(FALSE);
    pStep->put_lExecutionStatus(4);
    pStep->put_lRelativePriority(3);
    pStep->put_szDescription(L"转换数据任务");
    pStep->put_szScriptLanguage(L"VBScript");
    pStep->put_szStepName(L"DTSStep_DTSDataPumpTask");
    pStep->put_szTaskName(L"DTSTask_DTSDataPumpTask");
    pPack->GetDTSStep2((IDispatch *)&objSteps, pStep, &obj);
    objSteps.Add(obj); Tasks objTasks(objpak2.GetTasks());
    pTask->put_bAllowIdentityInserts(FALSE);
    pTask->put_bUseFastLoad(TRUE);
    pTask->put_lDataPumpOptions(0);
    pTask->put_lDestinationConnectionID(2);
    pTask->put_lExceptionFileOptions(1);
    pTask->put_lFastLoadOptions(2);
    pTask->put_lFetchBufferSize(1);
    pTask->put_lInsertCommitSize(0);
    pTask->put_lMaximumErrorCount(0);
    pTask->put_lProgressRowCount(1000);
    pTask->put_lSourceConnectionID(1);
    pTask->put_szDataPumpTaskName(L"DTSTask_DTSDataPumpTask");
    pTask->put_szDescription(L"转换数据任务");
    pTask->put_szDestinationObjectName(L"[pubs].[dbo].[test041210]");
    pTask->put_szExceptionFileColumnDelimiter(L"\t");
    pTask->put_szExceptionFileName(L"c:\\ddd.txt");
    pTask->put_szExceptionFileRowDelimiter(L"\r\n");
    pTask->put_szExceptionFileTextQualifier(L"\"");
    pTask->put_szSourceObjectName(L"C:\\bbb.txt");
    pTask->put_varFirstRow(_variant_t("0"));
    pTask->put_varLastRow(_variant_t("0"));
    IDispatch* objDataPumpTask = NULL;
    pPack->GetDTSDataPumpTask2((IDispatch *)objTasks, pTask, &objDataPumpTask);

    IDispatch* objTrans = NULL;
    pPack->GetDTSTransformations((IDispatch *)pTask, &objTrans);
    // Transformations objTrans = (Transformations)obj;
    pTran->put_bForceBlobsInMemory(FALSE);
    pTran->put_lForceSourceBlobsBuffered(0);
    pTran->put_lInMemoryBlobSize(1048576);
    pTran->put_lTransformFlags(63);
    pTran->put_lTransformPhases(4);
    pTran->put_szTransformation2Name(L"DTSTransformation");
    IDispatch* objTran = NULL;
    pPack->GetDTSTransformation2(objTrans, pTran, &objTran); IDispatch* objCol1s = NULL;
    pPack->GetDTSSourceColumns(objTran, &objCol1s);
    Columns objSourceColumns = (Columns)objCol1s;
    pCol1->put_bNullable(TRUE);
    pCol1->put_lDataType(130);
    pCol1->put_lFlags(32);
    pCol1->put_lNumericScale(0);
    pCol1->put_lOrdinal(1);
    pCol1->put_lPrecision(0);
    pCol1->put_lSize(11);
    pCol1->put_szColumnName(L"Col001");
    IDispatch* objCol1 = NULL;
    pPack->GetDTSSourceColumn(objCol1s, pCol1, &objCol1);
    objSourceColumns.Add(objCol1); IDispatch* objCols2 = NULL;
    pPack->GetDTSDestinationColumns(objTran, &objCols2);
    Columns objDestColumns = (Columns)objCols2;
    pCol2->put_bNullable(TRUE);
    pCol2->put_lDataType(129);
    pCol2->put_lFlags(24);
    pCol2->put_lNumericScale(0);
    pCol2->put_lOrdinal(1);
    pCol2->put_lPrecision(0);
    pCol2->put_lSize(11);
    pCol2->put_szColumnName(L"Mobile");
    IDispatch* objCol2 = NULL;
    pPack->GetDestinationColumn(objCols2, pCol2, &objCol2);
    objSourceColumns.Add(objCol2); int nRet;
    pPack->ExecutePackage2((IDispatch *)&objpak2, (IDispatch *)&objTasks, objDataPumpTask, objTrans, objTran,&nRet);
    }
      

  2.   

    提示的错误是:
    0xC0000005: Access Violation
      

  3.   

    你在返回之前没有AddRef,局部变量超出作用域的时候把对象释放了
      

  4.   

    非常感谢 jiangsheng(蒋晟.MSMVP2004Jan),我在将一个类的对象作为一个接口方法的输出参数(返回值)时,是调用了调用了该对象的QueryInterface方法来实现的,这样我在调用该接口方法时就可以正确的返回对象了,即(上面的第一个接口方法改为,只改了一行,请看注释):
    [id(22), helpstring("设计DTS包类的属性")] HRESULT GetDTSPackage2([out, retval]IDispatch **pPackage2);STDMETHODIMP CDTSPackage2::GetDTSPackage2(IDispatch **pPackage2)
    {
    AFX_MANAGE_STATE(AfxGetStaticModuleState()) CoInitialize(NULL);
    _Package2 objPackage2;
    if (!objPackage2.CreateDispatch("DTS.Package2"))
    {
    m_dwErrorNumber = ERROR_PACKAGE2CREATEDISPATCH;
    *pPackage2 = NULL;
    return S_OK;
    } try
    {
    objPackage2.SetName(m_dtsPackage2.szPackageName);
    objPackage2.SetWriteCompletionStatusToNTEventLog(m_dtsPackage2.bWriteCompletionStatusToNTEventLog);
    objPackage2.SetFailOnError(m_dtsPackage2.bFailOnError);
    objPackage2.SetPackagePriorityClass(m_dtsPackage2.lPackagePriorityClass);
    objPackage2.SetMaxConcurrentSteps(m_dtsPackage2.lMaxConcurrentSteps);
    objPackage2.SetLineageOptions(m_dtsPackage2.lLineageOptions);
    objPackage2.SetUseTransaction(m_dtsPackage2.bUseTransaction);
    objPackage2.SetTransactionIsolationLevel(m_dtsPackage2.lTransactionIsolationLevel);
    objPackage2.SetAutoCommitTransaction(m_dtsPackage2.bAutoCommitTransaction);
    objPackage2.SetRepositoryMetadataOptions(m_dtsPackage2.lRepositoryMetadataOptions);
    objPackage2.SetUseOLEDBServiceComponents(m_dtsPackage2.bUseOLEDBServiceComponents);
    objPackage2.SetLogToSQLServer(m_dtsPackage2.bLogToSQLServer);
    objPackage2.SetLogServerFlags(m_dtsPackage2.lLogServerFlags);
    objPackage2.SetFailPackageOnLogFailure(m_dtsPackage2.bFailPackageOnLogFailure);
    objPackage2.SetExplicitGlobalVariables(m_dtsPackage2.bExplicitGlobalVariables);
    objPackage2.SetPackageType(m_dtsPackage2.lPackageType);
    ////////////////////
    objPackage2.SetDescription(m_dtsPackage2.szDescription);
    objPackage2.SetLogFileName(m_dtsPackage2.szLogFileName);
    objPackage2.SetLogServerName(m_dtsPackage2.szLogServerName);
    objPackage2.SetLogServerPassword(m_dtsPackage2.szLogServerPassword);
    objPackage2.SetLogServerUserName(m_dtsPackage2.szLogServerPassword);
    }
    catch (_com_error &e)
    {
    *pPackage2 = NULL;
    PrintComError(e);
    m_dwErrorNumber = ERROR_PACKAGE2CREATEDISPATCH;
    return S_OK;
    } m_dwErrorNumber = 0;
    //*pPackage2 = objPackage2;
             objPackage2.m_lpDispatch->QueryInterface(IID_IDispatch, (void **)pPackage2);    //将上面一行替换成该行
    memset(&m_dtsPackage2, 0, sizeof(m_dtsPackage2));
    return S_OK;
    }
    但是,在我的第二个回复中提到的函数pPack->ExecutePackage2((IDispatch *)&objpak2, (IDispatch *)&objTasks, objDataPumpTask, objTrans, objTran,&nRet)的最后一句还是出现了同样的错误,不知是何原因,下面放出该函数的代码。
      

  5.   

    HRESULT ExecutePackage2([in]IDispatch** pDTSPackage2, [in]IDispatch** pDTSTasks, [in]IDispatch** pDTSTask, [in]IDispatch** pDTSTransformations, [in]IDispatch** pDTSTransformation2, [out,retval]int *pRet);STDMETHODIMP CDTSPackage2::ExecutePackage2(IDispatch** pDTSPackage2, IDispatch** pDTSTasks, IDispatch** pDTSTask, IDispatch** pDTSTransformations, IDispatch** pDTSTransformation2, int *pRet)
    {
    AFX_MANAGE_STATE(AfxGetStaticModuleState()) _Package2 objPak;
    objPak.AttachDispatch(*pDTSPackage2);
    Tasks objTasks;
    objTasks.AttachDispatch(*pDTSTasks);
    Task objTask;
    objTask.AttachDispatch(*pDTSTask);
    Transformations objTrans;
    objTrans.AttachDispatch(*pDTSTransformations);
    Transformation2 objTran;
    objTran.AttachDispatch(*pDTSTransformation2); try
    {
    objTrans.Add(objTran);
    objTasks.Add(objTask); szTemp = objPak.GetName();  //可以正常的通过该方法获得该对象的一个属性 objPak.Execute();      //该行出现了跟前面所说的同样的错误0xC0000005: Access Violation,不知是不是这个方法要使用的其他的对象不可用,很郁闷。 }
    catch (_com_error &e)
    {
    if (objTran != NULL)
    {
    objTran.ReleaseDispatch();
    objTran = NULL;
    }
    if (objTrans != NULL)
    {
    objTrans.ReleaseDispatch();
    objTrans = NULL;
    }
    if (objTasks != NULL)
    {
    objTasks.ReleaseDispatch();
    objTasks = NULL;
    }
    if (objTask != NULL)
    {
    objTask.ReleaseDispatch();
    objTask = NULL;
    } PrintComError(e);
    *pRet = m_dwErrorNumber = ERROR_EXECUTEPACKAGE2;
    return S_OK;
    } *pRet = m_dwErrorNumber = 0;
    return S_OK;
    }我的COM主要实现的是DTS,调用SQLSERVER提供的dtspack.dll来实现的。请求各位大侠指点。
    思归、孟子E章、天下、各位大侠快来帮忙呀!感激不尽!
      

  6.   

    jiangsheng(蒋晟.MSMVP2004Jan)
    说的没有错啊。
    _Package2 objPackage2;这是个局部变量啊。怎么可以这么分配呢。
      

  7.   

    hjunxu(hjun)的意思是我应该怎么做呢?
      

  8.   

    _Package2 objPackage2;
    这样声明一个类的变量有问题吗?
    我在将这个对象传出时调用objPackage2.m_lpDispatch->QueryInterface(IID_IDispatch, (void **)pPackage2); 我认为,这行代码实现了将对象objPackage2传出,该方法就使接口的计数器加1,所以我可以在其他接口函数中使用该对象了,是不是这样的呢?
      

  9.   

    IDispatch *patch;//或者你自己定义的接口指针和响应的IID
    bjPackage2.m_lpDispatch->QueryInterface(IID_IDispatch, (void **)&patch);
      

  10.   

    不明白seman(西曼) 说得是什么意思,我现在好像就是这样做的呀?
      

  11.   

    我只是一时兴致,没有看楼主的问题,只是简单的推荐一下而已,楼主有兴趣可以看下下面的文章
    http://dev.csdn.net/article/27/27324.shtm
    (如果文不对题就算了)