简体   繁体   English

COM DLL调用WCF服务的问题

[英]Issues with COM DLL calling WCF Service

I have a WCF Service which has a contract like this: (the operation contract is OneWay) 我有一个WCF服务,其合同如下:(操作合同为OneWay)

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

I have to call this SendEmpUpdate method from a COM DLL. 我必须从COM DLL调用此SendEmpUpdate方法。 I searched in the web and found some examples but that was for vb. 我在网上搜索并找到了一些示例,但这是针对vb的。 My COM component was developed in C++. 我的COM组件是用C ++开发的。 I followed the same steps for doing it in C++. 我按照相同的步骤在C ++中进行操作。

The Link which I followed: 我关注的链接:

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

This link explains about two ways of doing it: 此链接说明了两种实现方法:

1.Consuming a WCF service using a typed contract 2.Consuming a WCF service using a MEX endpoint 1.使用类型化合同使用WCF服务2.使用MEX端点使用WCF服务

I tried in both ways: (C++) 我尝试了两种方式:(C ++)

The 2nd way (Consuming a WCF service using a MEX endpoint) please see the below code: 第二种方式(使用MEX端点使用WCF服务)请参见以下代码:

The 2nd way works fine if I change OperationContract IsOneWay to false for SendEmpUpdate. 如果将SendEmpUpdate的OperationContract IsOneWay更改为false,则第二种方法可以正常工作。 If its true the Invoke method is failing with HRESULT value 0x80131502 (it seems to be like a ArgumentOutOfRangeException uses the HRESULT COR_E_ARGUMENTOUTOFRANGE) 如果为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);
}

The 1st method (Consuming a WCF service using a typed contract) please see the below code: 第一种方法(使用类型化的合同使用WCF服务),请参见以下代码:

In the 1st method CoGetObject is failing objEmp is null. 在第一种方法中,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);
}

Questions: 问题:

  1. If I set IsOneWay to true in the 2nd way, it's failing, how to fix this issue? 如果我以第二种方式将IsOneWay设置为true,则失败,如何解决此问题?
  2. Why CoGetObject is failing in the 1st way how to fix it? 为什么CoGetObject在第一种方法失败的解决方法?
  3. If any one way works 1st or 2nd it would be really helpful. 如果第一种或第二种方法都可行,那将非常有帮助。 There are no example in the web. 网上没有任何例子。

First off...sorry your dealing with COM! 首先...很抱歉您与COM打交道!

We had the occasion recently to consume a 4.0 WCF service (via httpBinding, though that shouldn't matter much, depending on version of .NET) from both C++ and VB6. 我们最近有机会使用C ++和VB6来使用4.0 WCF服务(通过httpBinding,尽管关系不大,具体取决于.NET的版本)。 I came across the same article(s) you probably did, and frankly, the COM Moniker goop is for the birds . 我碰到了您可能做过的同一篇文章,并且坦率地讲, COM Moniker护罩适用于鸟类 I was never successful in getting it working in a reliable fashion. 使它以可靠的方式工作从未使我成功。 Could be I'm just ignorant. 可能我只是一无所知。

Unfortunately, there is a pooh ton of 'legacy' code out there that is built on COM. 不幸的是,那里有很多基于COM构建的“遗留”代码。

Instead, we were very successful in creating a .NET assembly with a facade to the actual WCF service proxy. 相反,我们非常成功地创建了带有实际WCF服务代理外观的.NET程序集。 We exposed the facade via .NET COM Interop and then delegated to the internal proxy clas, which was generated by Add Service Reference wizard. 我们通过.NET COM Interop公开了外观,然后将其委派给内部代理类,该类由“添加服务引用”向导生成。 Beyond a little duplicated code, it worked like a champ while allowing downlevel clients to consume a SOAP based endpoint over HTTP. 除了少量重复的代码外,它还像冠军一样工作,同时允许低级客户端通过HTTP使用基于SOAP的端点。

Check out MSDN Example COM Class for how to decorate your facade class that will be exposed via COM Interop. 请查看MSDN 示例COM类,以了解如何装饰将通过COM Interop公开的外观类。 It describes the magic sprinkle of attributes your types will need to be exposed to a COM aware client. 它描述了您的类型需要向COM感知客户端公开的属性的神奇效果。

Basic outline is 基本轮廓是

  1. Build your .NET assembly, which is just a facade to your .NET service proxy and exposes your types 构建您的.NET程序集,它只是.NET服务代理的基础,并公开您的类型
  2. Call Regasm.exe with /TLB flag to generate the typelib that will make life easy from COM clients such as C++/VB6 调用带有/ TLB标志的Regasm.exe生成typelib,它将使来自COM客户端(例如C ++ / VB6)的生活变得轻松
  3. Reference that TLB (via #import) from the client, in your case I believe C++. 从客户端引用该TLB(通过#import),在您的情况下,我相信C ++。 You'll have strong types (eg MyClassPtr) which can be used to invoke your service, via your .NET COM Interop facade. 您将拥有强类型(例如MyClassPtr),这些类型可用于通过.NET COM Interop外观调用服务。
  4. Be sure to call CoInitialize to get COM ready and CoUninitialize to tear it down when your done. 确保完成后,调用CoInitialize来准备COM,并调用CoUninitialize来拆除它。

You might need to completely borrow tips from Reading WCF Configuration from a Custom Location on how to load up binding, and endpoint, configuration that might not be in the expected mayapp.exe.config if you don't 'own' the host. 您可能需要完全借鉴“从自定义位置读取WCF配置”中有关如何加载绑定和终结点的技巧,如果您不“拥有”主机,则可能不在预期的mayapp.exe.config中。

Not exactly the answer your looking for, hopefully someone with the this experience will post. 并非您要找的答案,希望有这种经验的人可以发表。

Z ž

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

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

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