2010-01-21 18 views
6

एटीएल (वीएस 2008) का उपयोग करके मैं किसी दिए गए आईडीस्पैच इंटरफ़ेस (IDispatch*) पर उपलब्ध उपलब्ध विधियों का आकलन कैसे कर सकता हूं? मुझे एक विशिष्ट नाम के साथ एक विधि की तलाश करने की आवश्यकता है और, मेरे पास DISPID होने के बाद, विधि का आह्वान करें (मुझे विधि के पैरामीटर पता है।) आदर्श रूप में मैं स्मार्ट COM पॉइंटर्स (CComPtr<>) का उपयोग करके ऐसा करना चाहता हूं।एटीएल का उपयोग कर गणना COM COM (IDISpatch) विधियां?

क्या यह संभव है?

+1

इस उपकरण (स्रोत कोड) देखें: http://sourceforge.net/projects/axfuzz/files/ – lsalamon

+0

और इस: http://www.codeproject.com/KB/atl/ienum.aspx – lsalamon

+0

मैं अन्य उदाहरणों की तलाश में गया और यह भी पाया कि http://spec.winprog.org/typeinf2/ –

उत्तर

7

जब तक ऑब्जेक्ट IDISpatchEx लागू नहीं करता है तब तक आप सभी उपलब्ध विधियों की गणना नहीं कर सकते हैं।

हालांकि, अगर आप जिस विधि को कॉल करना चाहते हैं उसका नाम पता है, तो आप उचित DISPID को नाम मैप करने के लिए GetIDsOfNames का उपयोग कर सकते हैं।

HRESULT hr; 
CComPtr<IDispatch> dispatch; 
DISPID dispid; 
WCHAR *member = "YOUR-FUNCTION-NAME-HERE"; 
DISPPARAMS* dispparams; 

// Get your pointer to the IDispatch interface on the object here. Also setup your params in dispparams. 

hr = dispatch->GetIDsOfNames(IID_NULL, &member, 1, LOCALE_SYSTEM_DEFAULT, &dispid); 
if (SUCCEEDED(hr)) { 
    hr = dispatch->Invoke(1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, dispparams, &varResult, NULL, NULL); 
} 

संपादित करें: पूर्णता के लिए, मुझे लगता है वहाँ ITypeInfo2 इंटरफ़ेस पूछताछ (यह मानते हुए वस्तु के लिए एक प्रकार लायब्रेरी है) है कि आप तरीकों की एक सूची के लिए IDispatch :: GetTypeInfo से प्राप्त एक तरीका है, लेकिन मैं मैंने यह नहीं किया है। दूसरा जवाब देखें।

+0

शानदार! मुझे जिस चीज की जरूरत थी। बहुत बहुत धन्यवाद। – Rob

+1

मेरा मानना ​​है कि मैंने आपके उत्तर में आपकी टिप्पणी में बस हर बिंदु बनाया है। कृपया इसे फिर से बारीकी से पढ़ें। इसके अलावा, पोस्टर सिर्फ एक विधि का आह्वान करने में सक्षम होना चाहता था जिसे वह पहले से ही जानता था। तो मेरे जवाब ने वह समाधान प्रदान किया जो वह वास्तव में करना चाहता था, जरूरी नहीं कि उसने क्या पूछा। यही कारण है कि, मुझे संदेह है, इसे सही उत्तर के रूप में चिह्नित किया गया था। और आखिरकार, कृपया शांत हो जाओ। यह केवल 1 एस और 0 है। –

15

आप टाइप जानकारी के माध्यम से IDispatch विधियों का आकलन कर सकते हैं। टाइप जानकारी प्राप्त करने के दो तरीके हैं:

  • डिस्पिंटरफेस के लिए टाइप लाइब्रेरी (यदि कोई है) के माध्यम से।
  • IDispatch::GetTypeInfo पर कॉल करके।

दुर्भाग्यवश, IDispatch कार्यान्वयन लागू करने वाले तरीकों और गुणों के बारे में प्रकार की जानकारी प्रदान करने के लिए बाध्य नहीं है।

यदि ऐसा है, तथापि, बुनियादी गणना ITypeInfo::GetTypeAttr बुला शामिल है अंतरफलक के लिए TYPEATTR पाने के लिए और लागू तरीकों (cFuncs) और चर (cVars) की संख्या को देखकर और इन पर पाशन और ITypeInfo::GetFuncDesc() या ITypeInfo::GetVarDesc() बुला। बेशक, यहां बहुत अधिक विवरण हैं जिनसे आपको निपटान करना होगा क्योंकि मैं यहां सूचीबद्ध कर सकता हूं, लेकिन यह आपकी खोज के लिए एक अच्छा प्रारंभिक बिंदु होना चाहिए।

यहां VB.Net में कोड के साथ एक अच्छा article explaining the process in more details है।

+0

अच्छी चीजें। इसे जोड़ने के लिए धन्यवाद। –

+0

@ फ्रांसी, जब कोई संपत्ति एक सरणी होती है, तो लौटाए गए VARDESC में एक varkind = IDispatch है। आप कैसे बता सकते हैं कि कोई संपत्ति एक सरणी है, और यदि कोई सरणी है - तो मैं अपने सदस्यों तक कैसे पहुंच सकता हूं? एक सरणी प्राप्त करने के लिए Invoke को कॉल करते समय परिणाम आईडीस्पैच होता है। यह आईडीस्पैच 'आइटम' या 'लंबाई' या किसी भी समान संपत्ति का समर्थन नहीं करता है। – Uri

+1

@Uri - ध्यान दें कि गुण फ़ील्ड नहीं हैं और इन्हें 'GetFuncDesc() 'के माध्यम से निरीक्षण किया जाना चाहिए जो आपको' FUNCDESC 'देता है, जहां से आपको' elemdescFunc '(वापसी के लिए) या' lprgelemdescParam') जाना है (के लिए पैरामीटर)। Arrays आमतौर पर आउट पैरामीटर के रूप में लौटाए जाते हैं, इसलिए आपको बाद वाले का निरीक्षण करना चाहिए। किसी भी मामले में, इनमें से दोनों 'ELEMDESC' देते हैं, जहां आपको 'tdesk' का निरीक्षण करना चाहिए, जो आपको 'TYPEDESC' देता है, जो' VARTYPE vt' पर आधारित है, वास्तव में 'ARRAYDESC' हो सकता है। यदि ऐसा है, तो आपके पास 'सुरक्षित' है। –

10

यहां कुछ कोड है जो गणना करता है (यह मानचित्र में [डिस्पैच आईडी] - [विधि नाम] जोड़ों को सम्मिलित करता है, लेकिन यह बदलना आसान है)।

/// 
/// \brief Returns a map of [DispId, Method Name] for the passed-in IDispatch object 
/// 
HRESULT COMTools::GetIDispatchMethods(_In_ IDispatch * pDisp, 
             _Out_ std::map<long, std::wstring> & methodsMap) 
{ 
    HRESULT hr = S_OK; 

    CComPtr<IDispatch> spDisp(pDisp); 
    if(!spDisp) 
     return E_INVALIDARG; 

    CComPtr<ITypeInfo> spTypeInfo; 
    hr = spDisp->GetTypeInfo(0, 0, &spTypeInfo); 
    if(SUCCEEDED(hr) && spTypeInfo) 
    { 
     TYPEATTR *pTatt = nullptr; 
     hr = spTypeInfo->GetTypeAttr(&pTatt); 
     if(SUCCEEDED(hr) && pTatt) 
     { 
      FUNCDESC * fd = nullptr; 
      for(int i = 0; i < pTatt->cFuncs; ++i) 
      { 
       hr = spTypeInfo->GetFuncDesc(i, &fd); 
       if(SUCCEEDED(hr) && fd) 
       { 
        CComBSTR funcName; 
        spTypeInfo->GetDocumentation(fd->memid, &funcName, nullptr, nullptr, nullptr); 
        if(funcName.Length()>0) 
        { 
         methodsMap[fd->memid] = funcName; 
        } 

        spTypeInfo->ReleaseFuncDesc(fd); 
       } 
      } 

      spTypeInfo->ReleaseTypeAttr(pTatt); 
     } 
    } 

    return hr; 

} 
+0

बढ़िया! यह कोड निर्बाध रूप से काम करता है – Elmue

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