2009-11-23 21 views
6

मेरे पास एक COM क्लास CMyCOMServer है, जो कि एक ही ऐप्लिकेशन में IMyInterface लागू करता है, दोनों सही GUID के साथ। CMyCOMServer::QueryInterface यदि IU अज्ञात या IMyInterface का अनुरोध किया गया है, तो S_OK (और स्वयं को सही प्रकार पर डालें) वापस कर देगा, अन्यथा यह E_NOINTERFACE लौटाता है।CoCreateInstance E_NOINTERFACE लौटा रहा है भले ही इंटरफ़ेस

एक ही पीसी पर एक और ऐप्लिकेशन में, मैं फोन:

HRESULT hr = ::CoCreateInstance(__uuidof(CMyCOMServer), 0, CLSCTX_SERVER, 
__uuidof(IMyInterface),(void **)&pInterface); 

यह रिटर्न E_NOINTERFACE। इसलिए मैंने माना कि मैं कुछ गलत कर रहा था और CMyCOMServer::QueryInterface पर ब्रेकपॉइंट जोड़ा। मैंने पाया कि जब CoCreateInstance कहा जाता है, QueryInterface अलग इंटरफेस के लिए कई बार शुरू हो रहा है:

  • पहले, IUnknown अनुरोध किया जाता है - कोई समस्या नहीं
  • फिर, IMarshall आदि जैसे कई इंटरफेस अनुरोध कर रहे हैं ... इन समर्थित नहीं हैं इसलिए E_NOINTERFACE
  • वापस आ गया है, अंत में, IMyInterface का अनुरोध किया गया है। मैं QueryInterface S_OK वापस आती है और इंटरफ़ेस सूचक के रूप में (IMyInterface *)this सेट के रूप में उम्मीद

तो मेरी भ्रम की स्थिति है क्यों बुला CoCreateInstance मुझे एक शून्य सूचक जा रहा है, सत्यापित करने और E_NOINTERFACE की वापसी कोड, जब COM सर्वर अनुप्रयोग स्पष्ट रूप से लौटा रहा है इंटरफ़ेस मैं पूछता हूं?

संपादित करें: मेरा क्लाइंट ऐप स्टार्टअप पर CoInitialize (NULL) को कॉल करता है, इससे कोई फर्क नहीं पड़ता।

+1

बस स्पष्ट करने के लिए: आपका COM सर्वर एक ऐप में चलाता है, और क्लाइंट एक और ऐप में चलता है? क्योंकि इसका मतलब है कि वे अलग-अलग प्रक्रियाओं में होंगे, और बदले में इसका मतलब है कि आप _need_ marshalling, संभवतः कस्टम। – MSalters

+0

हां वे करते हैं। 1 पीसी पर दो अलग-अलग ऐप्स। हालांकि मुझे पहले मार्शलिंग के साथ कभी गड़बड़ नहीं हुई थी, इसलिए मैं उलझन में हूं। मैंने पहले ही इसके बारे में सुना और मैंने COM विकास की उचित मात्रा में काम किया है। –

उत्तर

5

यदि आपका COM सर्वर एक अलग प्रक्रिया में चल रहा है, या एक ही प्रक्रिया में एक अलग अपार्टमेंट है, तो COM को यह जानने की आवश्यकता है कि जब आप अपने इंटरफ़ेस पर कॉल करते हैं तो पैरामीटर को कैसे पैकेज और ट्रांसमिट करना है। इस प्रक्रिया को "मार्शलिंग" कहा जाता है।

यदि आप एक कस्टम इंटरफेस को परिभाषित करते हैं, तो आपको निम्नलिखित दृष्टिकोणों में से किसी एक का उपयोग करके इसके लिए मार्शलिंग लागू करने की आवश्यकता है।

  • स्टैंडर्ड प्रमुखता: MIDL संकलक एक प्रॉक्सी और ठूंठ जो आप सिस्टम पर रजिस्टर करना होगा उत्पन्न करने के लिए किया है। यह शायद सबसे अच्छा विकल्प है क्योंकि आपने पहले ही अपना इंटरफ़ेस परिभाषित किया है।
  • OLE स्वचालन प्रमुखता: यदि आप एक स्वचालन संगत कस्टम इंटरफ़ेस को परिभाषित करने और marshaller कस्टम प्रमुखता जो पहले से ही कॉम ढांचे
  • का हिस्सा है का उपयोग करें: आप IMarshal
  • की
तरीकों को लागू

जब आप अपने COM सर्वर को डिबग कर रहे हों, हालांकि आप देखते हैं कि आप QueryInterface पर कॉल में अपना कस्टम इंटरफ़ेस वापस कर रहे हैं, तो यह प्रक्रिया सीमा पार नहीं करता है क्योंकि COM यह नहीं समझ सकता कि इंटरफ़ेस को मार्शल कैसे करें ऐस, इसलिए क्लाइंट E_NOINTERFACE देखता है।

अद्यतन (अपनी टिप्पणी के आधार पर)

इस अगर एक मौजूदा COM सर्वर अनुप्रयोग तो आप शायद पहले से ही एक प्रॉक्सी/स्टब है है। आपको इसे क्लाइंट और सर्वर दोनों पर पंजीकृत करने की आवश्यकता है। क्या यह हो सकता है कि आप इसे एक नई मशीन पर जांच रहे थे और आप बस इसे पंजीकृत करना भूल गए? पंजीकरण करने के लिए आप बस प्रॉक्सी/स्टब डीएल पर regsvr32 करते हैं। क्योंकि वास्ते इंटरफ़ेस याद आ रही है काफी मददगार था

+0

जैसा कि मैंने कहा, सर्वर ऐप नया कोड नहीं है। यह पहले से ही एक लाइव सिस्टम में उपयोग किया जाता है - इंटरफ़ेस या कुछ भी में कोई बदलाव नहीं। सर्वर पक्ष पर कुछ भी बदलना एक विकल्प नहीं है, मुझे अपने नए क्लाइंट ऐप को वहां से क्या करना है, क्योंकि अन्य क्लाइंट किसी भी तरह ऐसा करने का प्रबंधन करते हैं। –

+0

मुझे लगता है कि यह सबसे अच्छा जवाब है। यह पता चला है कि हमारे पास एक प्रॉक्सी-स्टब डीएलएल है, मुझे बस इसके बारे में पता नहीं था। Regsvr32 का उपयोग करके इसे ठीक किया गया। –

2

क्या यह थ्रेडिंग मॉडल समस्या हो सकती है जो Raymond Chen wrote about?

टिप्पणी के जवाब में संपादित करें:।

अपने सूत्रण मॉडल वस्तु आप बना रहे हैं, में और अगर उसके बाद COM मार्शलिंग किक के सूत्रण मॉडल के साथ असंगत है तो मार्शलिंग सामान वहाँ नहीं है , त्रुटि जो बाहर आती है वह E_NOINTERFACE है, क्योंकि marshalling इंटरफ़ेस गुम है।

यह वास्तव में मार्शलिंग के मुकाबले मॉडलों को थ्रेड करने के बारे में अधिक है।

+0

हो सकता है, लेकिन मैंने कभी भी मार्शलिंग का उपयोग नहीं किया है और जहां तक ​​मुझे इस परियोजना पर 3 साल तक काम करने के बाद पता है, 100 से अधिक COM सर्वर EXE/DLLs के साथ। कोई कस्टम marshalling या फैंसी थ्रेडिंग सामान कहीं भी किया जाता है। तो मैं उलझन में हूं कि अब यह एक समस्या क्यों होनी चाहिए। –

5

ऐसा इसलिए होता है क्योंकि COM उपप्रणाली आपके कस्टम इंटरफ़ेस (IMyInterface) को मार्शल करने की कोशिश करती है और उसे यह नहीं पता कि उसे कैसे करना है। ऐसा इसलिए होता है क्योंकि सर्वर आउट-प्रो है या क्योंकि सर्वर इन-प्रो है और उपभोक्ता अनुप्रयोग का थ्रेड जो CoCreateInstance() को कॉल करता है, को गलत तरीके से CoInitialize()/CoInitializeEx() कहा जाता है ताकि "मल्टीथ्रेडेड अपार्टमेंट" का उल्लेख किया गया हो लेख में user Thomas दूसरे उत्तर में संदर्भित करता है।

आप केवल सुनिश्चित करने के द्वारा एक में proc सर्वर आप को दबाने सकता है मार्शलिंग की जरूरत है कि धागा CoCreateInstance बुला() या तो CoInitialize() या CoInitializeEx() कॉल COINIT_APARTMENTTHREADED साथ लागू करने हेतु "एकल पिरोया अपार्टमेंट"।

यदि आपको आउट-प्रो सर्वर की आवश्यकता है तो आप मार्शलिंग के आसपास नहीं जा सकते हैं।उत्तरार्द्ध मामले में आप निम्न में से एक कर सकता है:

  • लागू IMarshal - कम से कम बेहतर
  • ऐड प्रॉक्सी/स्टब्स और अपने कस्टम इंटरफेस के लिए उन्हें रजिस्टर
  • (यकीन है कि अगर यह बाहर के लिए काम करेंगे नहीं proc, लेकिन यह सबसे आसान है) यदि आपके इंटरफ़ेस को ऑटोमेशन मार्शलर के साथ मार्शल किया जा सकता है तो बस अपने COM सर्वर के संसाधनों में एक टाइपप्लिब शामिल करें और रजिस्ट्री में उस टाइपेलिब को पंजीकृत करें।
+0

मुझे नहीं पता कि इसका क्या अर्थ है! मुझे संदेह है कि मैंने किया है, मेरी समस्या हल हो सकती है। –

+1

क्या आपने वह लेख पढ़ा है? – sharptooth

+0

हां अब मेरे पास है। यह प्रासंगिक दिखता है लेकिन मुझे कोई विचार नहीं देता कि क्या बदलना है। सर्वर ऐप वर्षों से चल रहा है और मैंने इसके साथ बातचीत करने के लिए एक नए ग्राहक एमएफसी ऐप को एक साथ फेंक दिया है। मुझे उस लेख में 'मार्शलिंग दबाने' के बारे में कोई उल्लेख नहीं है। –

0

पिछली टिप्पणी के बारे में E_NOINTERFACE लौटे तथापि, हमारे लिए इस सवाल का जवाब/ठीक मुख्य आवेदन (एक बुला CoCreateInstance) STA (एकल थ्रेड फ्लैट) होने के लिए मजबूर करने के लिए किया गया था, और इस के लिए एक उन्नत लिंकर विकल्प सेट द्वारा किया गया था, अर्थात्:

"CLR थ्रेड गुण" "एसटीए सूत्रण विशेषता" करने के लिए

या लिंक कमांड लाइन आप पर सेट किया गया है कार्य करें:

"/CLRTHREADATTRIBUTE:STA" 

इस एमटीए और एसटीए, जो धागे भर में एक फोन का कारण बनता है का एक मिश्रण से बचाता है।

आशा है कि किसी और को यह उपयोगी लगेगा।

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