2010-04-16 21 views
9

मैं Excel फ़ाइल से कुछ डेटा पढ़ने के लिए एक C++ एप्लिकेशन पर काम कर रहा हूं। मुझे यह काम मिल गया है, लेकिन मैं एक हिस्से के बारे में उलझन में हूँ। यहां कोड है (केवल पहले सेल को पढ़ने के लिए सरलीकृत)।CoUninitialize क्यों बाहर निकलने पर त्रुटि का कारण बनता है?

//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 को असम्बद्ध किया जाता है, तो मुझे प्रोग्राम से बाहर निकलने पर comip.h में _Release फ़ंक्शन में प्रवेश उल्लंघन मिलता है।

यह comip.h से कोड है, जो इसके लायक है।

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

मैं COM प्रोग्रामिंग के साथ बहुत अनुभवी नहीं हूं, इसलिए शायद कुछ स्पष्ट है जो मुझे याद आ रही है।

  1. CoUninitialize को कॉल अपवाद क्यों देता है?

  2. CoUninitialize को कॉल करने के नतीजे क्या हैं?

  3. क्या मैं यहां कुछ पूरी तरह गलत कर रहा हूं?

+0

AFAIK वास्तव में इस स्थिति में CoUninitialize को कॉल करने में कोई हानि नहीं है क्योंकि आपकी प्रक्रिया वैसे भी बंद हो रही है (इसी तरह गतिशील रूप से आवंटित स्मृति को मुक्त नहीं करना ठीक है क्योंकि ओएस प्रक्रिया को साफ करते समय इसे मुक्त कर दिया जाएगा) । लेकिन इसे कॉल करना एक अच्छी आदत है, क्योंकि जब आप इसे समाप्त करने वाले नहीं होते हैं, तो जब आप इसे एक अलग स्थिति में कर सकते हैं। –

उत्तर

12

आपके पास जो समस्या है वह एक दायरा है। संक्षिप्त जवाब है कि 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; 
} 

लंबा जवाब यह है कि पीटीआरएस विनाशकों (जो रिलीज कहते हैं) मुख्य से बाहर निकलने पर बुलाए जा रहे हैं। यह CoUnit के बाद है, मूल रूप से, आपके ऐप और COM ऑब्जेक्ट के बीच संचार चैनल को बंद कर देता है।

CoUnit को कॉल करने के नतीजे क्या हैं? कम से कम प्रो-सर्वर प्रो सर्वर के लिए, वास्तव में कोई नकारात्मक परिणाम नहीं है।

+0

धन्यवाद। मैंने कहीं और एक समान सुझाव देखा लेकिन स्पष्टीकरण समझ में नहीं आया। मेरे लिए इसे साफ़ करने के लिए धन्यवाद। –

3

एक सुरुचिपूर्ण समाधान CoInitializeEx और CoUninitialize को अपनी कक्षा में रखना है। यह Raymond Chen article देखें।

1

CoInitialize का अर्थ आपके धागे को एक अपार्टमेंट में दर्ज करना है; और CoUninitialize अपार्टमेंट से अपने धागे को हटा देता है।

जब आप किसी अपार्टमेंट में नहीं होते हैं तो इंटरफ़ेस पॉइंटर का उपयोग करना समस्या का कारण बनता है क्योंकि आपको केवल उस अपार्टमेंट में कच्चे इंटरफ़ेस पॉइंटर का उपयोग करने की अनुमति है। (आप इंटरफ़ेस पॉइंटर को किसी अन्य अपार्टमेंट में मार्शल कर सकते हैं इसे किसी अन्य अपार्टमेंट में उपयोग करें)।

जब आप इंटरफ़ेस पॉइंटर के माध्यम से कॉल करते हैं, और ऑब्जेक्ट दूसरे अपार्टमेंट में रहता है (जो इस मामले में सच है), तो आपका इंटरफ़ेस सूचक अपार्टमेंट में प्रॉक्सी ऑब्जेक्ट में कॉल करता है जो तब आरपीसी के माध्यम से स्टब के साथ संचार करता है गंतव्य अपार्टमेंट में। अगर आपने अपार्टमेंट छोड़ दिया था (CoUninitialize कर कर) तो यह परिवहन आपकी त्रुटि के कारण और उपलब्ध नहीं होगा।

यदि कभी-कभी इन-प्रोसेस सर्वर का उपयोग करना आप रिलीज कॉल करने से पहले CoUninitialize करने से दूर हो सकते हैं क्योंकि इसमें कोई परिवहन परत शामिल नहीं है, लेकिन यह एक अच्छा विचार नहीं है।

बीटीडब्ल्यू, CoInitialize पर दूसरा तर्क निर्दिष्ट करता है कि आप एक एसटीए दर्ज करना चाहते हैं (यानी।आपका धागा आपके अपार्टमेंट में एकमात्र धागा होगा; और जब आप ऐसा करते हैं तो एक नया अपार्टमेंट बनाया जाता है), या एमटीए (जिसमें से एक प्रति प्रक्रिया है)।

विकल्प COINIT_APARTMENTTHREADED और COINIT_MULTITHREADED क्रमशः हैं; आपने 0 निर्दिष्ट किया है जो वास्तव में COINIT_MULTITHREADED है। IMHO यह जादू कोड के बजाय आपके कोड में प्रतीकात्मक नाम का उपयोग करने के लिए स्पष्ट होगा।

संबंधित मुद्दे