Почему CoUninitialize вызывает ошибку на выходе?

Я работаю над приложением C++ для чтения некоторых данных из файла Excel. У меня есть он работа, но я смущен одной частью. Вот код (упрощен до только для чтения первая ячейка).

//Mostly copied from http://www.codeproject.com/KB/wtl/WTLExcel.aspx

#import "c:\Program Files\Common Files\Microsoft Shared\OFFICE11\MSO.DLL"
#import "c:\Program Files\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.OLB"
#import "C:\Program Files\Microsoft Office\Office11\excel.exe" rename ("DialogBox","ExcelDialogBox") rename("RGB","ExcelRGB") rename("CopyFile", "ExcelCopyFile") rename("ReplaceText", "ExcelReplaceText") exclude("IFont", "IPicture")

_variant_t varOption((long) DISP_E_PARAMNOTFOUND, VT_ERROR);

int _tmain(int argc, _TCHAR* argv[])
{
    DWORD dwCoInit = 0;
    CoInitializeEx(NULL, dwCoInit);
    Excel::_ApplicationPtr pExcel;    
    pExcel.CreateInstance(_T("Excel.Application"));
    Excel::_WorkbookPtr pBook;
    pBook = pExcel->Workbooks->Open("c:\\test.xls", varOption, varOption, varOption, varOption, varOption, varOption, varOption, varOption, varOption, varOption, varOption, varOption);
    Excel::_WorksheetPtr pSheet = pBook->Sheets->Item[1];
    Excel::RangePtr pRange = pSheet->GetRange(_bstr_t(_T("A1")));
    _variant_t vItem = pRange->Value2;
    printf(_bstr_t(vItem.bstrVal));    
    pBook->Close(VARIANT_FALSE);
    pExcel->Quit();
    //CoUninitialize();
    return 0;
}

Я должен был прокомментировать вызов к CoUninitialize для программы для работы. Когда CoUninitialize не прокомментирован, я получаю нарушение прав доступа в функции _Release в comip.h на выходе программы.

Вот код от comip.h, если это имеет значение.

void _Release() throw()
{
    if (m_pInterface != NULL) {
        m_pInterface->Release();
    }
}

Я не очень опытен с программированием COM, таким образом, существует, вероятно, что-то очевидное, которое я пропускаю.

  1. Почему делает вызов к причине CoUninitialize исключение?

  2. Каковы последствия не вызова CoUninitialize?

  3. Я делаю что-то полностью неправильно здесь?

10
задан John M Gant 16 April 2010 в 15:05
поделиться

1 ответ

Проблема, с которой вы столкнулись, связана с областью действия. Краткий ответ - переместить CoInit и CoUninit во внешнюю область из Ptrs. Например:

//Mostly copied from http://www.codeproject.com/KB/wtl/WTLExcel.aspx

#import "c:\Program Files\Common Files\Microsoft Shared\OFFICE11\MSO.DLL"
#import "c:\Program Files\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.OLB"
#import "C:\Program Files\Microsoft Office\Office11\excel.exe" rename ("DialogBox","ExcelDialogBox") rename("RGB","ExcelRGB") rename("CopyFile", "ExcelCopyFile") rename("ReplaceText", "ExcelReplaceText") exclude("IFont", "IPicture")

_variant_t varOption((long) DISP_E_PARAMNOTFOUND, VT_ERROR);

int _tmain(int argc, _TCHAR* argv[])
{
    DWORD dwCoInit = 0;
    CoInitializeEx(NULL, dwCoInit);
    {
        Excel::_ApplicationPtr pExcel;    
        pExcel.CreateInstance(_T("Excel.Application"));
        Excel::_WorkbookPtr pBook;
        pBook = pExcel->Workbooks->Open("c:\\test.xls", varOption, varOption, varOption, varOption, varOption, varOption, varOption, varOption, varOption, varOption, varOption, varOption);
        Excel::_WorksheetPtr pSheet = pBook->Sheets->Item[1];
        Excel::RangePtr pRange = pSheet->GetRange(_bstr_t(_T("A1")));
        _variant_t vItem = pRange->Value2;
        printf(_bstr_t(vItem.bstrVal));    
        pBook->Close(VARIANT_FALSE);
        pExcel->Quit();
    }
    CoUninitialize();
    return 0;
}

Более длинный ответ заключается в том, что деструкторы Ptrs (вызывающие Release) вызываются при выходе из main. Это после CoUnit, который, по сути, отключает канал связи между вашим приложением и COM-объектом.

Каковы последствия отказа от вызова CoUnit? Для недолговечных внутрипроцессных COM-серверов нет никаких негативных последствий.

15
ответ дан 3 December 2019 в 18:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: