हम एक देशी सी ++ आवेदन जो COM से अधिक विभिन्न प्रकार के कुछ VBA मैक्रो का समर्थन करता है है के माध्यम से लागू बुला। इन प्रकार में से एक, VBAExtension
, कोर सी ++ आवेदन के साथ ही पंजीकृत करता है (एक वर्ग से प्राप्त) IConnectionPointImpl<Extension, &DIID_IExtensionEvents, CComDynamicUnkArray>
का एक उदाहरण हो जाती है। यह ठीक काम करता है; कोर और अन्य वीबीए मैक्रोज़ दोनों उपयुक्त VBAExtension ऑब्जेक्ट दिए गए, IxtensionEvents पर विधियों तक पहुंच सकते हैं।समस्याएं सी से IConnectionPointImpl इंटरफ़ेस ++ मोडल WinForms
हम यह भी एक .NET विधानसभा (सी # में लिखा) है, जिसकी रन-टाइम में कोर आवेदन करने के लिए लोड किया जाता है है। ऐतिहासिक कारणों से, असेंबली एक ऑटो-रनिंग वीबीए मैक्रो द्वारा लोड की जाती है; फिर, जब उपयोगकर्ता एक विशेष बटन दबाता है, तो दूसरा वीबीए मैक्रो असेंबली का मुख्य प्रवेश बिंदु चलाता है, जो आगे की बातचीत के लिए System.Windows.Forms
संवाद लाता है।
सेटअप है कि। मैं .NET असेंबली के भीतर से VBAExtension
विधियों तक पहुंचने वाले कुछ अजीब व्यवहार को देख रहा हूं। विशेष रूप से, मैं विधानसभा में विभिन्न स्थानों से निम्नलिखित कोड चला रहा हूँ:
foreach (VBAExtension ve in app.Extensions)
{
System.Diagnostics.Debug.Print("Ext: " + ve.Name);
}
अगर मैं विधानसभा के मुख्य वस्तु के निर्माता से चलाने के; या असेंबली के मुख्य प्रवेश बिंदु से (संवाद प्रदर्शित होने से पहले), सबकुछ ठीक है - मुझे VBAExtension
प्रिंट किए गए नाम मिलते हैं।
हालांकि, अगर मैं एक आदेश से एक ही कोड को चलाने के विधानसभा के दशक में एक बटन से शुरू हुआ (मोडल - हम कॉल कर रहे हैं form.ShowDialog()
) WinForm, ve.Name
सब खाली कर रहे हैं। pDispatch->Invoke
कॉल IConnectionPointImpl
उपवर्ग द्वारा किए गए सफल होता है (S_OK रिटर्न), लेकिन किसी भी वापसी वार्स निर्धारित नहीं करता है।
अगर मैं संवाद बदल होने की गैर मोडल (form.Show()
साथ लागू), तो नाम फिर से काम करते हैं। प्रपत्र की विधि (मोडलनेस?) इस बात को प्रभावित करती है कि IConnectionPointImpl
कॉल सफल हैं या नहीं।
किसी को भी पता है कि क्या हो रहा है?
संपादित करें: पहली पोस्टिंग के बाद से, मैंने दिखाया है कि यह आविष्कार कॉल स्टैक नहीं है; इसके बजाए, यह है कि कॉल एक मोडल संवाद से बना है या नहीं। मैंने मुख्य पाठ अपडेट किया है।
संपादित करें 2: प्रति हंस Passant का जवाब है, यहाँ अपने नैदानिक प्रश्नों के उत्तर दिए गए हैं:
- जैसी उम्मीद थी, अच्छा (मोडहीन) मामले में कोई त्रुटि है, तो मैं VBA ईवेंट हैंडलर का नाम बदलने । कॉल बस कोई डेटा नहीं देता है।
- मैंने वीबीए हैंडलर में एक संदेश बॉक्स कॉल किया है; यह मॉडल केस में प्रदर्शित होता है, लेकिन मोडल मामले में नहीं है। Ergo, हैंडलर मोडल मामले में निष्पादित नहीं किया गया है।
Err
के उपयोग से, मैं बता सकता हूं कि यदि हमने वीबीए हैंडलर में अपवाद मारा है तो हमें वीबीए त्रुटि संवाद मिलता है। एक बार इसे साफ़ करने के बाद, C++Invoke
कॉल में 0x80020009 ("अपवाद हुआ") रिटर्न कोड के रूप में है, और सामान्य विफलता मानों के साथ भरने वाले PExcepInfo (VBA ने वास्तविक विवरण निगल लिया है)- ईवेंट दूसरे प्रदर्शन पर आग नहीं लगाता है मोडल डायलॉग, या तो तुरंत पहले संवाद के बाद या सी # एड-इन के दूसरे आमंत्रण के दौरान।
मैं अगले संदेश के रूप में हमारे संदेश loops में खोदने की कोशिश करूंगा।
'IConnectionPointImpl' घटनाओं के बारे में है और अपने foreach पाश विस्तार संपत्ति सीधे तक पहुँच रहा है, तो आप क्यों लगता है कि' IConnectionPointImpl' यहां शामिल कर रहा है? इसे और अधिक समझ बनाने यदि आपका कोड स्निपेट था सी ++ कोड कुछ ईवेंट हैंडलर के अंदर चल रहा है और कि बाहरी नाम संपत्ति क्वेरी होगा, लेकिन इस स्निपेट सी ++ तो और सी # में तुम्हारा होना होगा। –
क्योंकि मैं आगे बढ़ सकता हूं और देख सकता हूं कि यह है। ध्यान दें कि 've' सी # में एक .NET ऑब्जेक्ट है जो 'नाम' संपत्ति का खुलासा करता है; कि संपत्ति ++ एक तरीका है जिसके VBA मैक्रो और 'Dispatch'es द्वारा पंजीकृत ICPI इंटरफ़ेस पाता द्वारा सी में समर्थित है प्रासंगिक ... उह ... _thing_, जो VBA कॉल जो नाम देता है बनाता है। यही है, कॉल सी # - (.NET) -> सी ++ - (IConnectionPointImp) -> वीबीए है। सी # -> वीबीए नहीं। – Chowlett
बस सुनिश्चित करें कि मैं इस अधिकार मिल गया बनाने के लिए: 've.Name' सी # कार्यान्वयन है, तो यह कुछ सी ++ कोड (COM इंटरफेस विधि?) कहता है, तो सी ++ कोड किसी भी तरह अपनी बातें, और यह के भाग के रूप में यह एक COM घटना मुद्दों करता है , जिसे कुछ वीबीए हैंडलर द्वारा नियंत्रित किया जाता है और यह हैंडलर प्रश्न में स्ट्रिंग का स्रोत होगा? फिर आप देखते हैं कि स्ट्रिंग गुम हो गई है (पहले से ही C++ कोड में 'आईडीस्पैच :: Invoke' के पूरा होने के बाद) जब यह सब निर्दिष्ट परिदृश्य में कहा जाता है। –