COM DLL调用WCF服务的问题

Job*_*boy 1 c# com wcf

我有一个WCF服务,它有这样的合同:(运营合同是OneWay)

[ServiceContract()]
public interface IEmpUpdate
{
    [OperationContract(IsOneWay = true)]
    void SendEmpUpdate(int _empid);
}
Run Code Online (Sandbox Code Playgroud)

我必须从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.使用类型化合同来消费WCF服务2.使用MEX端点来消费WCF服务

我试过两种方式:(C++)

第二种方式(使用MEX端点使用WCF服务)请参阅以下代码:

如果我为SendEmpUpdate将OperationContract IsOneWay更改为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);
}
Run Code Online (Sandbox Code Playgroud)

第一种方法(使用类型化合约使用WCF服务)请参阅以下代码:

在第一种方法中,CoGetObject失败,objEmp为null.


//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);
}
Run Code Online (Sandbox Code Playgroud)

问题:

  1. 如果我以第二种方式将IsOneWay设置为true,那么它是否失败,如何解决这个问题?
  2. 为什么CoGetObject在第一种方式失败如何修复它?
  3. 如果任何一种方式适用于第一或第二,那将非常有帮助.网上没有例子.

Zac*_*ham 5

首先......对不起你与COM打交道!

我们最近有机会使用来自C++和VB6的4.0 WCF服务(通过httpBinding,尽管这应该不重要,具体取决于.NET的版本).我偶然发现了你可能做的同一篇文章,坦率地说,COM Moniker goop是为了鸟类.我从未成功地以可靠的方式工作.可能我只是无知.

不幸的是,有一大堆基于COM的"遗留"代码.

相反,我们非常成功地创建了具有实际WCF服务代理的外观的.NET程序集.我们通过.NET COM Interop公开了外观,然后委托给由Add Service Reference向导生成的内部代理clas.除了一些重复的代码之外,它还像冠军一样工作,同时允许下层客户端通过HTTP使用基于SOAP的端点.

查看MSDN 示例COM类,了解如何装饰将通过COM Interop公开的Facade类.它描述了您的类型需要暴露给COM感知客户端的神奇的属性.

基本概要是

  1. 构建.NET程序集,它只是.NET服务代理的外观并公开您的类型
  2. 使用/ TLB标志调用Regasm.exe以生成类型库,这将使COM客户端(如C++/VB6)变得简单
  3. 从客户端引用TLB(来自#import),在你的情况下我相信C++.您将拥有强大的类型(例如MyClassPtr),可用于通过.NET COM Interop外观调用您的服务.
  4. 确保调用CoInitialize以准备好COM,并在完成后将CoUninitialize拆除.

您可能需要从自定义位置完全借阅阅读WCF配置中的提示,了解如何加载绑定和端点,如果您没有"拥有"主机,那么配置可能不在预期的mayapp.exe.config中.

不完全是你想要的答案,希望有这种经验的人会发帖.

ž