Проблемы с COM DLL, вызывающей WCF Service - PullRequest
1 голос
/ 30 марта 2011

У меня есть служба WCF, у которой есть такой контракт: (контракт операции OneWay)

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

Мне нужно вызвать этот метод SendEmpUpdate из COM DLL.Я искал в Интернете и нашел несколько примеров, но это было для 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. Использование службы WCF с использованием конечной точки MEX

Я пробовал обоими способами: (C ++)

2-й способ (Потреблениеслужба WCF, использующая конечную точку MEX), см. следующий код:

2-й способ работает нормально, если я изменяю OperationContract IsOneWay на false для SendEmpUpdate.Если это правда, метод 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);
}

1-й метод (использование службы WCF с использованием aнабранный контракт) см. следующий код:

В первом методе 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. Если 2-й способ установить значение IsOneWay в значение true, это не помогает, как решить эту проблему?
  2. Почему 1-й способ CoGetObject завершается ошибкой?
  3. Если имеетсяспособ работает 1 или 2, это было бы очень полезно.В сети нет примеров.

Ответы [ 2 ]

5 голосов
/ 30 марта 2011

Прежде всего ... извините, что вы имеете дело с COM!

Недавно у нас была возможность использовать сервис 4.0 WCF (через httpBinding, хотя это не должно иметь большого значения, в зависимости от версии .NET)как из C ++, так и из VB6.Я наткнулся на ту же статью (статьи), которую вы, вероятно, сделали, и, честно говоря, COM Moniker Goop для птиц .Мне никогда не удавалось заставить его работать надежно.Может быть, я просто не знаю.

К сожалению, существует огромное количество «устаревшего» кода, построенного на COM.

Вместо этого мы очень успешно создали .NET-сборку с фасадом, на самом делеСервисный прокси WCF.Мы выставили фасад через .NET COM Interop, а затем делегировали внутреннему прокси-классу, сгенерированному мастером Add Service Reference.Помимо небольшого дублированного кода, он работал как первоклассный инструмент, позволяя клиентам более низкого уровня использовать конечную точку на основе SOAP через HTTP.

Ознакомьтесь с MSDN Пример COM-класса о том, как декорировать ваш фасадный класс, которыйбудет выставлен через COM Interop.В нем описывается магическое распространение атрибутов, которые ваши типы должны будут предоставлять клиенту с поддержкой COM.

Базовая схема

  1. Создайте сборку .NET, которая является лишь фасадом дляваш прокси-сервер службы .NET и предоставляет ваши типы
  2. Call Regasm.exe с флагом / TLB для создания библиотеки типов, которая облегчит жизнь клиентам COM, таким как C ++/ VB6
  3. Ссылка, что TLB (через #import) от клиента, в вашем случае я верю C ++.У вас будут сильные типы (например, MyClassPtr), которые можно использовать для вызова вашего сервиса через ваш фасад .NET COM Interop.
  4. Обязательно вызовите CoInitialize, чтобы получить COM, и CoUninitialize разорвите его, когда вашготово.

Возможно, вам придется полностью позаимствовать советы из Чтение конфигурации WCF из пользовательского местоположения о том, как загрузить привязку и конечную точку, конфигурацию, которая может не соответствовать ожидаемой.mayapp.exe.config, если вы не «владеете» хостом.

Не совсем тот ответ, который вы ищете, надеюсь, кто-то с таким опытом напишет.

Z

0 голосов
/ 30 марта 2011

Возможный ответ на вопрос 2: в этом случае у вашего моникера отсутствует префикс схемы "service:".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...