VC++中 COM的方法說明

CoInitialize   
說明 :CoInitialize是Windows提供的API函數,用來告訴 Windows以單線程的方式創建com對象。應用程序調用com庫函數(除CoGetMalloc內存分配函數)之前必須初始化com庫。

語法:HRESULT CoInitialize(_In_opt_  LPVOID pvReserved);
參數被保留,且必須爲NULL。[1]

返回值:
S_OK : 該線程中COM庫初始化成功。
S_FALSE: 該線程中COM庫已經被初始化 CoInitialize () 標明以單線程方式創建。[1]
使用 CoInitialize 創建可以使對象直接與線程連接,得到最高的性能。
CoInitialize並不裝載COM 庫,它只用來初始化當前線程使用什麼樣的套間。使用這個函數後,線程就和一個套間建立了對應關係。線程的套間模式決定了該線程如何調用COM對象,是否需要列集等。
CoInitialize ()並不會干擾客戶和服務器之間的通信,它所做的事情是讓線程註冊一個套間,而線程運行過程中必然在此套間。
CoInitialize和CoUninitialize必須成對使用。
創建新的應用程序就調用CoInitializeEx代替CoInitialize。

CoInitializeEx
函數說明:
CoInitializeEx是 Windows提供的API函數,爲當前線程初始化COM庫並設置併發模式 。應用程序調用com庫中的函數(除CoGetMalloc內存分配函數)之前必須初始化com庫。
函數原型
HRESULT CoInitializeEx(
void * pvReserved,
DWORD dwCoInit
);
參數介紹:
pvReserved
系統 保留的參數,必須傳入 NULL.
dwCoInit
該標示指明基於當前線程的併發模式和初始化選項。該參數是 COINIT 枚舉類型,傳入參數時候,除了
COINIT_APARTMENTTHREADED 和COINIT_MULTITHREADED標記外,其餘的標記可以組合使用。
返回值:
S_OK :COM庫初始化成功。
S_FALSE :當前線程上,COM庫已經被初始化。
RPC_E_CHANGED_MODE :COM庫已經被初始化且傳入參數設置的併發模式和本次不同。
注意事項:
        在應用程序中使用COM庫,至少要調用一次CoInitializeEx函數(通常也就調用一次)。如果傳入參數的併發標誌相同
,單個線程也可以多次調用該函數,但後來有效的調用將返回 S_FALSE。在正常關閉COM庫情況下,每一個CoInitialize 或者CoInitializeEx的成功的調用(也包含返回S_FALSE的調用),都必須用通Uninitialize函數來結束。
使用函數 CoInitializeEx的代碼的前面需要包含於處理標誌 #define _WIN32_DCOM
基於線程的併發模式一旦設置,將不能再改變。一個線程上調用CoInitializeEx如果與原來調用設置的併發模式不一致,將會失敗並返回RPC_E_CHANGED_MODE。
CoInitializeSecurity
Registers security and sets the default security values for the process. This function is called exactly once per process, either explicitly or implicitly. It can be called by the client, server, or both. For legacy applications and other applications that do not explicitly call CoInitializeSecurity, COM calls this function implicitly with values from the registry. If you set processwide security using the registry and then call CoInitializeSecurity, the AppID registry values will be ignored and theCoInitializeSecurity values will be used.
註冊並設置進程的默認的安全值。該函數只被每個進程確切的調用一次,以顯式或隱式的方式。它可以被客戶端,服務器端或是兩邊都調用。對於非COM的應用程序不應該顯式的被調用,但是對於COM應用程序該函數會隱式的從註冊表讀取參數來調用。如果你使用註冊表設置進程級的安全然後調用CoInitializeSecurity, 那麼AppID的註冊表值會被忽略而使用CoInitializeSecurity值。從這段話中,我們可以知道兩個信息,一,CoInitializeSecurity函數用於設置進程安全;二,只能被進程調用一次。第一點是說明用途,而第二點說明用法。很簡單,只要在CoInitialize()後面調用一下就可以。但是請記住一定要用下面的方式去驗證返回值:
複製代碼

HRESULT hr;

hr 
=
 CoInitialzieSecurity();
if (SUCCEED(hr) || RPC_E_TOO_LATE ==
 hr)
{
    
do
 your work;
}
複製代碼
因爲你如果在開發一個多線程的程序並且多人一起開發,你很可能不知道誰在你之前已經調了一次,而這種問題又很難去定位,特別是你沒有別人代碼的情況下。下面是四個返回值的說明:
複製代碼

This function supports the standard return value E_INVALIDARG, as well as the following: 

S_OK 

Indicates success.

RPC_E_TOO_LATE 

CoInitializeSecurity has already been called.

RPC_E_NO_GOOD_SECURITY_PACKAGES 

asAuthSvc was not NULL, and none of the authentication services 
in the list could be registered. Check the results saved in asAuthSvc for
 authentication service–specific error codes.

E_OUT_OF_MEMORY 

Out of memory.
複製代碼



strncpy_s( dest, _countof(dest), src, count );

並且這句代碼不是在所有平臺上都有問題。
這個我今天也是在牛人的幫助下才找出來的,而最大地問題是它出現在同一是雙核的只是速度不同的w2k3機器上,一臺百分百返回S_OK; 而另一臺百分百返回RPC_E_TOO_LATE,而且用的同樣的代碼。所以初步懷疑是多線程時序的問題。不得不承認調試很難^_^。順便提一句,大家看到這樣的代碼hang在那裏會有什麼想法:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章