2011-03-30 97 views
1

問題我有有這樣的合同WCF服務:(承包經營爲單向)與COM DLL調用WCF服務

[ServiceContract()] 
public interface IEmpUpdate 
{ 
    [OperationContract(IsOneWay = true)] 
    void SendEmpUpdate(int _empid); 
} 

我要調用從COM DLL此SendEmpUpdate方法。我在網上搜索,發現了一些例子,但這是爲vb。我的COM組件是用C++開發的。我遵循相同的步驟在C++中完成它。

的鏈接,我跟着:

http://pieterderycke.wordpress.com/2010/10/05/using-the-wcf-service-moniker-to-communicate-between-legacy-com-applications-and-new-net-applications/

此鏈接解釋了有關兩個方面做的:

使用合同 一個類型1.Consuming WCF服務2.Consuming WCF服務使用MEX端點

我以兩種方式嘗試:(C++)

的第二WA y(使用MEX端點消費WCF服務)請參閱下面的代碼:

如果將OperationContract IsOneWay更改爲SendEmpUpdate的false,則第二種方法可以正常工作。如果其真正的Invoke方法與HRESULT值0x80131502失敗(這似乎是像 ArgumentOutOfRangeException使用HRESULT COR_E_ARGUMENTOUTOFRANGE)


//Importing the tlb: 

#import "Employee.tlb" no_namespace named_guids 

//Creating the moniker string: 

LPTSTR moniker = L"service:mexaddress=net.tcp://localhost:11234/Employee/mex, " 
      L"address=net.tcp://localhost:11234/Employee, " 
      L"contract=IEmpUpdate, " 
      L"binding=nettcpEmpUpdate, "; 

//Get the Object: 

HRESULT hr = S_FALSE; 
IDispatch* objWsc; 

hr = CoGetObject(moniker, NULL, IID_IDispatch, (void**)&objWsc); 

if (FAILED(hr)) 
{ 
    Message(TEXT("Client: CoGetObject"), hr); 
    return(hr); 
} 

DISPID dispid; 
BSTR pOperation = L"SendEmpUpdate"; 

hr = objWsc->GetIDsOfNames(
    IID_NULL, 
    &pOperation, 
    1, 
    LOCALE_SYSTEM_DEFAULT, 
    &dispid); 

if (FAILED(hr)) 
{ 
    Message(TEXT("Client: GetIDsOfNames"), hr); 
    return(hr); 
} 

DISPPARAMS empIDs; 
VARIANTARG varData[1]; 
empIDs.rgvarg = &varData[0]; 

VariantInit(&empIDs.rgvarg[0]); 
empIDs.rgvarg[0].vt = VT_I4; 
empIDs.rgvarg[0].lVal = 564234; 

empIDs.cArgs = 1; 
empIDs.cNamedArgs = 0; 
empIDs.rgdispidNamedArgs = NULL; 

VARIANT result; 
//VariantInit(&result); 
UINT argErr = 0; 

EXCEPINFO pExcepInfo; 
memset(&pExcepInfo, 0, sizeof(EXCEPINFO)); 

hr = objWsc->Invoke(
    dispid, 
    IID_NULL, 
    LOCALE_SYSTEM_DEFAULT, 
    DISPATCH_METHOD, 
    &empIDs, &result, &pExcepInfo, &argErr); 

if (FAILED(hr)) 
{ 
    Message(TEXT("Client: Invoke"), hr); 
    return(hr); 
} 

首屆方法(使用類型化的消費WCF服務合同)請參閱以下代碼:

在第一種方法CoGetObject失敗objEmp爲空。


//Importing the tlb: 

#import "Employee.tlb" no_namespace named_guids 

//Creating the moniker string: 

LPTSTR moniker = L"address=net.tcp://localhost:11234/Employee, " 
      L"contract={52DEEE76-0BAF-31D8-A48B-DA2C50FA2753}, " 
      L"binding=nettcpEmpUpdate "; 

//Get the Object: 

HRESULT hr = S_FALSE; 
IEmpUpdate* objEmp; 

hr = CoGetObject(moniker, NULL, __uuidof(IEmpUpdate), (void**)&objEmp); 

if (FAILED(hr)) 
{ 
    Message(TEXT("Client: CoGetObject"), hr); 
    return(hr); 
} 

問題:

  1. 如果我在第2路組IsOneWay爲true,它的失敗,如何解決這個問題?
  2. 爲什麼CoGetObject在第一種方式失敗,如何解決它?
  3. 如果任何一種方法工作的第一或第二,這將是非常有益的。網絡中沒有例子。

回答

5

首先...對不起你處理COM!

我們最近有一次從C++和VB6中消耗4.0 WCF服務(通過httpBinding,儘管這應該不會太大,取決於.NET的版本)。我碰到了你可能做過的同一篇文章,坦率地說,COM Moniker goop是爲鳥類。我從未成功地以可靠的方式開展工作。可能是我只是無知。

不幸的是,有一大堆'遺留'代碼在那裏建立在COM上。相反,我們非常成功地創建了一個帶有Facade實際WCF服務代理的.NET程序集。我們通過.NET COM Interop公開了Facade,然後委託給由Add Service Reference嚮導生成的內部代理clas。除了一些重複的代碼之外,它像冠軍一樣工作,同時允許低級客戶端通過HTTP使用基於SOAP的端點。

查看MSDN Example COM Class瞭解如何修飾將通過COM Interop公開的外觀類。它描述了你的類型需要暴露給一個COM感知客戶端的神奇噴灑屬性。

基本輪廓是

  1. 建立你的.NET程序集,這僅僅是一個門面到你的.NET服務 代理和暴露你的類型
  2. 呼叫Regasm.exe/TLB標誌生成類型庫,這將使生活變得容易從COM客戶端如 作爲C++/VB6
  3. 引用TLB(通過#import)從客戶端,你的情況我相信C++。 您將擁有強大的類型(例如 MyClassPtr),可用於通過您的.NET 調用您的服務。
  4. 一定要調用CoInitialize以獲取COM就緒,並在完成後使用CoUninitialize將其關閉。

您可能需要完全從Reading WCF Configuration from a Custom Location如何加載結合借入的技巧,和端點,配置,可能無法在預期的mayapp.exe.config如果你沒有自己的「主機。

不完全是您尋找的答案,希望有此經驗的人可以發佈。

ž

+0

我有過類似的經歷。 C#COM包裝器似乎很容易工作。我同意Zach在這裏,但我希望有人確實有現成的代碼解決方案。 – 2011-03-30 02:48:01

+0

感謝您的回答。我只是按照您在基本大綱中提到的方式遵循相同的方式,即使使用強類型MyClassPtr,我的COM組件如何解決我的調用,它應該知道我的服務在哪裏運行(例如,哪個端口,哪個端口界面等) – Joboy 2011-03-30 02:51:15

+0

@Joboy你的權利,該信息將來自你的正常綁定配置,但你可能需要從一個已知的位置加載它。例如d:\ config \ client.config(或工作目錄),它將包含客戶端代碼解析地址,綁定和合同所需的configuration/serviceModel元素。我同意它在WCF以外什麼是正常的,但是恕我直言,它更容易管理,理解和測試你在.NET,WCF而不是COM上的工作。 COM ......給我一些想法的震顫。 :)查看答案中的第二個鏈接,其中包含一個示例(不是我的)的鏈接。 – 2011-03-30 11:14:19

0

地回答問題2:你的名字是缺少其計劃前綴「service:」在這種情況下。