CoInitialize()和AfxOleInit()區別

來源:互聯網
上載者:User

CoInitialize()和AfxOleInit()都是初始化COM庫,可它們有什麼不同呢 


    OLE是建立在COM之上的技術,層次比COM要高。AfxOleInit()調用的是OleInitialize(),而 OleInitialize()除了調用CoInitializeEx()來初始化COM庫外,還進行一些其它的操作,這些操作對OLE應用來說是必須的,這些OLE應用程式套件括:  

    (1)Clipboard;  

    (2)Drag   and   drop;  

    (3)Object   linking   and   embedding(現在的OLE,已不再僅僅是Object   linking   and   embedding的概念);  

    (4)In-place   activation;  

    與AfxOleInit()對應的是,AfxOleTerm()。  


    AfxOleInit()和AfxOleTerm()其實也是需要成對的,但是,在你的程式中,AfxOleTerm()可以不出現,這是因為,MFC已經幫你做好了(有興趣的話,你可以仔細研究一下CWinThread::m_lpfnOleTermOrFreeLib,而CWinApp是從CWinThread繼承的)。

注:但是當你的函數出現了重複調用AfxOleInit()時間便不能依靠mfc自動調用了,需要顯式的調用AfxOleTerm清理com庫


CoInitialize與 AfxOleInit

使用MFC的控制台主程式中如果用AfxOleInit()初始化com就會出現DLL中調用wordApp.CreateDispatch("Word.Application",NULL)失敗,而改用用CoInitialize()則會成功

在AfxOleInit()函數中設定斷點調試之後可以知道: afxContextIsDLL這個標誌的值為ture,因而它並不會去調用 OleInitialize ,進而不會調用 CoInitialize.

MSDN(If AfxOleInit is called from an MFC DLL, the call will fail. The failure
occurs because the function assumes that, if it is called from a DLL, the OLE system was previously initialized by the calling application.) 看來在這個函數中把當前項目當做DLL來處理了.^_^,不知是不是MFC本身的bug

BOOL AFXAPI AfxOleInit()

{

    _AFX_THREAD_STATE* pState = AfxGetThreadState();

    ASSERT(!pState->m_bNeedTerm);    // calling it twice?


    // Special case DLL context to assume that the calling app initializes OLE.

    // For DLLs where this is not the case, those DLLs will need to initialize

    // OLE for themselves via OleInitialize.  This is done since MFC cannot provide

    // automatic uninitialize for DLLs because it is not valid to shutdown OLE

    // during a DLL_PROCESS_DETACH.
    if (afxContextIsDLL)

    {

        pState->m_bNeedTerm = -1;  // -1 is a special flag

        return TRUE;

    } 


    // first, initialize OLE

    SCODE sc = ::OleInitialize(NULL);

    if (FAILED(sc))

    {

        // warn about non-NULL success codes

#ifdef _DEBUG

        TRACE(traceOle, 0, _T("Warning: OleInitialize returned scode = %s.\n"),

            AfxGetFullScodeString(sc));

#endif

        goto InitFailed;

    }

    // termination required when OleInitialize does not fail

    pState->m_bNeedTerm = TRUE;


    // hook idle time and exit time for required OLE cleanup

    CWinThread* pThread; pThread = AfxGetThread();

    ASSERT(pThread);

    pThread->m_lpfnOleTermOrFreeLib = AfxOleTermOrFreeLib;


    // allocate and initialize default message filter

    if (pThread->m_pMessageFilter == NULL)

    {

        pThread->m_pMessageFilter = new COleMessageFilter;

        ASSERT(AfxOleGetMessageFilter() != NULL);

        AfxOleGetMessageFilter()->Register();

    }

    return TRUE;


InitFailed:

    AfxOleTerm();

    return FALSE;

}

轉載一下問題

I have been debugging an MFC application that calls AfxOleInit() to initialize COM. The call has returned true, but I am catching COM exceptions when trying to instantiate and use any COM objects - the error says that COM has not been initialized. After stepping
into the AfxOleInit method, I can see why this is happening - There is a macro named 'afxContextIsDLL' that is returning true, and this is causing AfxOleInit to immediatly return without calling OleInitialize. According to the documentation located here (http://msdn2.microsoft.com/en-us/library/e91aseaz(VS.80).aspx),
this is expected behavior "If AfxOleInit is called from an MFC DLL". However, my application is an exe. 


From there, I created a new Win32 Console Application with MFC header files as a Windows application project to see if it was a project setting. Upon calling AfxOleInit in InitInstance, I see the same behavior. I then created an new Win32 Console Application
with MFC header files as a Console application project. The call to AfxWinInit trips up on the same macro (afxContexIsDLL) and never calls AfxInitThread. I have also added a call to AfxOleInit to this project and I am seeing the same behavior - OleInitialize
never gets called. 


The strange thing is that there are other projects in the application that are executables, and call AfxOleInit successfully (ie, stepping into this method, the macro afxContextIsDLL is false, and OleInitialize gets called). The only difference is that these
projects were created with an earlier version of Visual Studio... This project was made with VS2K5. Suspecting that it had to do with some project setting, I made a copy of one of these executables' project file, 'gutted' it by adding the new application's
files and include libraries, but still am seeing


COM中CoInitializeEx 與CoInitialize的區別

    CoInitialize、CoInitializeEx都是windows的API,主要是告訴windows以什麼方式為程式建立COM對象,原因是程式調用com庫函數(除CoGetMalloc和記憶體配置函數)之前必須初始化com庫。
    CoInitialize指明以單線程方式建立。

    CoInitializeEx可以指定COINIT_MULTITHREADED以多線程方式建立。 

    建立單線程方式的COM伺服器時不用考慮序列化問題,多線程COM伺服器就要考慮。

    CoInitialize並不裝載com庫,這個函數只是用來初始化當前線程使用什麼樣的套間。當使用這個函數以後,線程就和一個套間建立了對應關係。

    線程的套間模式決定了該線程如何調用com對象,是否需要列集等

    套間是com中用來解決並發調用衝突的很有效辦法

    Before calling any COM functions, a thread needs to call CoInitialize to load the COM infrastructure (and to enter an apartment). Once a thread calls CoInitialize, the thread is free to call COM APIs.

    CoInitializeEx provides the same functionality as CoInitialize and also provides a parameter to explicitly specify the thread's concurrency model. The current implementation of CoInitialize calls CoInitializeEx and specifies the concurrency model as single-thread
apartment. Applications developed today should call CoInitializeEx rather than CoInitialize.

    註:新的應用程式應該調用CoInitializeEx而不是CoInitialize,否則就會有必要在之後每個調用Com的線程中調用CoInitialize來初始化出每個線程自己的套間。

引用MSDN,有興趣的看下吧

   A thread must call CoInitializeEx or CoInitialize before calling any other COM library function except the CoGetMalloc function and other memory allocation calls (CoTaskMemAlloc, CoTaskMemFree,
CoTaskMemReAlloc, and the IMalloc methods on the task allocation supplied by CoGetMalloc). Otherwise, the COM library function will return CO_E_NOTINITIALIZED.


Once the concurrency model for a thread is set, it cannot be changed. A call to CoInitializeEx on a thread that was previously initialized with a different concurrency model will fail and return RPC_E_CHANGED_MODE. 


If neither concurrency model is specified by the dwCoInit parameter, the default is COINIT_MULTITHREADED.


Objects created in a single-threaded apartment (STA) receive method calls only from their apartment's thread, so calls are serialized and arrive only at message-queue boundaries (when the Win32 function PeekMessage or SendMessage is called).


Objects created on a COM thread in a multithread apartment (MTA) must be able to receive method calls from other threads at any time. You would typically implement some form of concurrency control in a multithreaded object's code using Win32 synchronization
primitives such as critical sections, semaphores, or mutexes to help protect the object's data. 


When an object that is configured to run in the neutral threaded apartment (NTA) is called by a thread that is in either an STA or the MTA, that thread transfers to the NTA. If this thread subsequently calls CoInitializeEx, the call fails and returns RPC_E_CHANGED_MODE.


CoInitializeEx provides the same functionality as CoInitialize and also provides a parameter to explicitly specify the thread's concurrency model. The current implementation of CoInitialize calls CoInitializeEx and specifies the concurrency model as single-thread
apartment. Applications developed today should call CoInitializeEx rather than CoInitialize. 


Because OLE technologies are not thread-safe, the OleInitialize function calls CoInitializeEx with the COINIT_APARTMENTTHREADED flag. As a result, an apartment that is initialized for multithreaded object concurrency cannot use the features enabled by OleInitialize.


Because there is no way to control the order in which in-process servers are loaded or unloaded, do not call CoInitialize, CoInitializeEx, or CoUninitialize from the DllMain function. 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.