2010-10-26 15 views
5

यहां एक ठोस उदाहरण है:क्या एक मार्शल इंटरफ़ेस को मार्शल करना मुझे प्रॉक्सी या मूल इंटरफ़ेस में मार्शलर देता है?

मैं wb.CoCreateInstance(CLSID_InternetExplorer, 0, CLSCTX_SERVER); पर कॉल करके IWeBrowser2 इंटरफ़ेस बना देता हूं। यह मुझे मेरी प्रक्रिया से एक मार्शल इंटरफेस देता है जो भी चल रहा है iexplore.exe प्रक्रियाओं में इस ब्राउज़र टैब को मेरे थ्रेड ए में शामिल किया जाता है।

अब मैं IGlobalInterfaceTable उपयोग करते हैं, इस इंटरफेस के लिए एक कुकी प्राप्त यह मेरी धागा को पारित करने के लिए और वहाँ से मार्शल इंटरफ़ेस का अनुरोध करें।

प्रश्न: मैं अपने धागा एक में या सीधे आईई प्रक्रिया में उदाहरण के लिए प्रॉक्सी के लिए एक प्रॉक्सी मिलता है?

यह मेरे लिए समझदार है कि मैं यह करने के लिए अपने स्वयं के संदर्भ में उदाहरण के लिए एक सीधा प्रॉक्सी मिल जाएगा लगता है,
तथापि:

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

संपादित करें: ओह, दोनों धागे एसटीए हैं।

उत्तर

2

अंत में मुझे यह पता लगाने में कुछ समय था कि क्या हो रहा है, इसलिए मैंने यह देखने के लिए एक छोटा परीक्षण लिखा कि क्या हो रहा है।

  • धागा कि पंजीकृत इंटरफ़ेस कुकी को अमान्य कर समाप्त:

    // MarshalTest.cpp : Defines the entry point for the console application. 
    // 
    
    #include "stdafx.h" 
    
    enum { WM_THEREYOUGO = WM_USER+1, WM_THANKYOU, WM_YOURWELCOME }; 
    
    DWORD WINAPI TheOtherThread(DWORD * main_thread_id) 
    { 
        MSG msg = { 0 }; 
        HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 
        assert(SUCCEEDED(hr)); 
    
        { 
         // create web browser 
         CComPtr<IWebBrowser2> wb; 
         hr = wb.CoCreateInstance(CLSID_InternetExplorer, 0, CLSCTX_SERVER); 
         assert(SUCCEEDED(hr) && wb); 
    
         // navigate 
         hr = wb->Navigate2(&CComVariant(_T("stackoverflow.com")), &CComVariant(0), &CComVariant(_T("")), &CComVariant(), &CComVariant()); 
         assert(SUCCEEDED(hr)); 
         hr = wb->put_Visible(VARIANT_TRUE); 
         assert(SUCCEEDED(hr)); 
    
         // Marshal 
         DWORD the_cookie = 0; 
         { 
          CComPtr<IGlobalInterfaceTable> com_broker; 
          hr = com_broker.CoCreateInstance(CLSID_StdGlobalInterfaceTable); 
          assert(SUCCEEDED(hr)); 
          hr = com_broker->RegisterInterfaceInGlobal(wb, __uuidof(IWebBrowser2), &the_cookie); 
         } 
    
         // notify main thread 
         PostThreadMessage(*main_thread_id, WM_THEREYOUGO, the_cookie, NULL); 
    
         // message loop 
         while(GetMessage(&msg, 0, 0, 0)) { 
          if(msg.hwnd == NULL) { 
           // thread message 
           switch(msg.message) { 
            case WM_THANKYOU: 
             PostQuitMessage(0); 
             break; 
           } 
          } else { 
           TranslateMessage(&msg); 
           DispatchMessage(&msg); 
          } 
         } 
        } 
    
        CoUninitialize(); 
    
        PostThreadMessage(*main_thread_id, WM_YOURWELCOME, 0, NULL); 
        return msg.wParam; 
    } 
    
    
    int _tmain(int argc, _TCHAR* argv[]) 
    { 
        MSG msg = {0}; 
        DWORD main_thread_id = GetCurrentThreadId(); 
    
        HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 
        assert(SUCCEEDED(hr)); 
        { 
         DWORD ThreadId = 0; 
         HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)TheOtherThread, &main_thread_id, 0, &ThreadId); 
    
         DWORD the_cookie = 0; 
    
         CComPtr<IWebBrowser2> wb, wb2; 
    
         while(GetMessage(&msg, 0, 0, 0)) { 
          if(msg.hwnd == NULL) { 
           // thread message 
           switch(msg.message) { 
            case WM_THEREYOUGO: 
             // we got the cookie. 
             the_cookie = msg.wParam; 
    
             // get the browser. This should work. 
             { 
              CComPtr<IGlobalInterfaceTable> com_broker; 
              hr = com_broker.CoCreateInstance(CLSID_StdGlobalInterfaceTable); 
              assert(SUCCEEDED(hr)); 
              hr = com_broker->GetInterfaceFromGlobal(the_cookie, __uuidof(IWebBrowser2), (void**)&wb); 
              assert(SUCCEEDED(hr) && wb); 
             } 
    
             // do something with it. 
             hr = wb->put_FullScreen(VARIANT_TRUE); 
             assert(SUCCEEDED(hr)); 
    
             // signal the other thread. 
             PostThreadMessage(ThreadId, WM_THANKYOU, 0, NULL); 
             break; 
    
            case WM_YOURWELCOME: 
             // the other thread has ended. 
             PostQuitMessage(0); 
             break; 
           } 
          } else { 
           TranslateMessage(&msg); 
           DispatchMessage(&msg); 
          } 
         } 
    
         // the other thread has ended. Try getting the interface again. 
         { 
          CComPtr<IGlobalInterfaceTable> com_broker; 
          hr = com_broker.CoCreateInstance(CLSID_StdGlobalInterfaceTable); 
          assert(SUCCEEDED(hr)); 
          hr = com_broker->GetInterfaceFromGlobal(the_cookie, __uuidof(IWebBrowser2), (void**)&wb2); 
          //assert(SUCCEEDED(hr) && wb2); // this fails, hr == E_INVALIDARG. 
    
          // clean up, will not be executed. 
          if(SUCCEEDED(hr)) { 
           hr = com_broker->RevokeInterfaceFromGlobal(the_cookie); 
          } 
         } 
    
         // try using it 
         if(wb2) { 
          hr = wb2->put_FullScreen(VARIANT_FALSE); 
          assert(SUCCEEDED(hr)); 
         } else if(wb) { 
          // this succeeds 
          hr = wb->put_FullScreen(VARIANT_FALSE); 
          assert(SUCCEEDED(hr)); 
         } 
    
         CloseHandle(hThread); 
        } 
    
        CoUninitialize(); 
        return msg.wParam; 
    } 
    

    लब्बोलुआब यह है।

  • पहले से ही मार्शल इंटरफेस वैध रहता है। (इस मामले में, वह है।)

इसका मतलब है कि मुझे अन्य थ्रेड के ऑब्जेक्ट की बजाय आईई प्रक्रिया में प्रॉक्सी मिलती है।

1

आपने पहले से ही एक प्रो-प्रॉक्सी प्राप्त की है क्योंकि आपने आउट-ऑफ-प्रोसेस सर्वर के लिए कहा था। आगे क्या होता है उस प्रकार के अपार्टमेंट पर निर्भर करता है जो थ्रेड ए रहता है, CoInitializeEx() के लिए तर्क। यदि यह एमटीए है तो आपको निश्चित रूप से थ्रेड बी में एक ही प्रॉक्सी मिल जाएगी, मान लीजिए कि यह एमटीए भी है। थ्रेड ए बाहर निकलने पर अतिरिक्त संदर्भ संख्या को जीवित रखना चाहिए। अगर यह एसटीए है तो मुझे 100% यकीन नहीं है लेकिन लगता है कि आपको एक नया प्राप्त करना चाहिए। बीटीडब्ल्यू का परीक्षण करने में आसान, केवल थ्रेड ए से एक का उपयोग करें और यदि आपको कोई नया निर्माण करना होगा तो आपको RPC_E_WRONGTHREAD मिल जाएगा।

मेरे पास एक महान स्पष्टीकरण नहीं है कि धागा ए बाहर निकलने के लिए थ्रेड बी के लिए प्रॉक्सी क्यों मारता है जब तक कि आप IGlobalInterfaceTable :: RevokeInterfaceFromGlobal() को कॉल न करें। जो आप आमतौर पर करेंगे।

+0

दोनों धागे एसटीए हैं। इसके अलावा, मैं RevokeInterfaceFromGlobal को कॉल नहीं करता हूं। GetInterfaceFromGlobal केवल E_INVALIDARG लौटाता है जब मैं थ्रेड ए समाप्त होने के बाद इसे कॉल करता हूं। – Fozi

+0

बहुत असामान्य। आप RevokeInterfaceFromGlobal कहां कह रहे हैं? –

+0

मेरे पास संदर्भ संदर्भित ऑब्जेक्ट है जो कुकी को संभालता है। जब सभी संदर्भ चले जाते हैं, तो इसे निरस्त कर दिया जाता है। कुकीज़ को पूल में रखा जाता है और बाहर निकलने पर जारी किया जाता है। – Fozi

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