繁体   English   中英

COM DLL调用WCF服务的问题

[英]Issues with COM DLL calling WCF Service

我有一个WCF服务,其合同如下:(操作合同为OneWay)

[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.使用类型化合同使用WCF服务2.使用MEX端点使用WCF服务

我尝试了两种方式:(C ++)

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

如果将SendEmpUpdate的OperationContract IsOneWay更改为false,则第二种方法可以正常工作。 如果为true,则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为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);
}

问题:

  1. 如果我以第二种方式将IsOneWay设置为true,则失败,如何解决此问题?
  2. 为什么CoGetObject在第一种方法失败的解决方法?
  3. 如果第一种或第二种方法都可行,那将非常有帮助。 网上没有任何例子。

首先...很抱歉您与COM打交道!

我们最近有机会使用C ++和VB6来使用4.0 WCF服务(通过httpBinding,尽管关系不大,具体取决于.NET的版本)。 我碰到了您可能做过的同一篇文章,并且坦率地讲, COM Moniker护罩适用于鸟类 使它以可靠的方式工作从未使我成功。 可能我只是一无所知。

不幸的是,那里有很多基于COM构建的“遗留”代码。

相反,我们非常成功地创建了带有实际WCF服务代理外观的.NET程序集。 我们通过.NET COM Interop公开了外观,然后将其委派给内部代理类,该类由“添加服务引用”向导生成。 除了少量重复的代码外,它还像冠军一样工作,同时允许低级客户端通过HTTP使用基于SOAP的端点。

请查看MSDN 示例COM类,以了解如何装饰将通过COM Interop公开的外观类。 它描述了您的类型需要向COM感知客户端公开的属性的神奇效果。

基本轮廓是

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

您可能需要完全借鉴“从自定义位置读取WCF配置”中有关如何加载绑定和终结点的技巧,如果您不“拥有”主机,则可能不在预期的mayapp.exe.config中。

并非您要找的答案,希望有这种经验的人可以发表。

ž

问题2的可能答案service:在这种情况下,您的绰号缺少其方案前缀“ service: ”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM