Вызов WCF-сервиса из неуправляемого C++ вызывает нарушение прав доступа
Я хочу получить доступ к wcf-сервису из неуправляемого кода. Служба просто соединяет строки и возвращает их, чтобы все было просто.
public class Stringconcat : IStringconcat
{
public string stringconcat(string a, string b)
{
return b + a;
}
}
[ServiceContract]
public interface IStringconcat
{
[OperationContract]
string stringconcat(string a, string b);
}
Я размещаю эту службу с помощью приложения aC# console, которое ссылается на.dll службы. И выставляет конечную точку для сервиса. В основном():
using (ServiceHost host = new ServiceHost(typeof(stringconcatservice.Stringconcat)))
{
host.Open();
Console.WriteLine("Press <ENTER> to terminate the host application");
Console.ReadLine();
}
Конфиг хоста выглядит так:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceMetadata />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="serviceBehavior"
name="stringconcatservice.Stringconcat" >
<endpoint address="stringconcat" binding="basicHttpBinding"
name="basicHttp" contract="stringconcatservice.IStringconcat" />
<endpoint binding="mexHttpBinding" name="mex"
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/stringconcatService" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>
Теперь все работает, если я вызываю службу из.net-клиента, который использует для ссылки на службу базовый адрес.
StringconcatClient proxy = new StringconcatClient();
string a = " string a ";
string b = " string b ";
string c = proxy.stringconcat(a, b);
Console.WriteLine(c);
Console.WriteLine("Press <ENTER> to terminate Client.");
Console.ReadKey();
Теперь к проблеме у меня есть. Потому что я хочу получить доступ к сервису из неуправляемого кода C++. Для этого я использую.dll, который регистрируется для com-взаимодействия, а также использует сервисную ссылку работающего хоста.
[Guid("E4435D3B-CBC3-4D41-B4A5-D8116B394195")]
[ClassInterface(ClassInterfaceType.None)]
[ComVisible(true)]
public class Stringconcat_IAMCOM : IStringconcat_IAMCOM
{
public string stringconcat(string a, string b)
{
StringconcatClient client = new StringconcatClient();
return client.stringconcat(a, b);
}
}
[Guid("E130F97E-1844-4C8B-9E57-AF42632A2557")]
[ComVisible(true)]
public interface IStringconcat_IAMCOM
{
[DispId(1)]
string stringconcat(string a, string b);
}
Теперь, когда я пытаюсь получить доступ к службе через посредника. DLL с C++...
#import "..\stringconcatInteropSvcClient\bin\Debug\stringconcatInteropSvcClient.tlb"
#include <iostream>
#include <stdio.h>
using namespace stringconcatInteropSvcClient;
int main(int argc, const char* argv[])
{
HRESULT hr = CoInitialize(NULL);
BSTR a = L" string a ";
BSTR b = L" string b ";
IStringconcat_IAMCOM* q;
hr = CoCreateInstance(__uuidof(Stringconcat_IAMCOM), NULL, CLSCTX_INPROC_SERVER,
__uuidof(IStringconcat_IAMCOM), (void**)&q );
std::cout << q->stringconcat(a, b);
//Uninitialize COM.
CoUninitialize();
return 0;
}
... я получаю исключение в stringconcatinteropsvcclient.tli как:
"Необработанное исключение в 0x75... в xyz.exe: исключение Microsoft C++: _com_error в расположении памяти 0x..."
тогда я могу продолжить и получить следующее исключение в strlen.asm:
"Необработанное исключение в 0x5d... (msvcr100d.dll) в xyz.exe: 0xC0...: расположение чтения нарушения доступа 0x00..."
после этого исключение прекращается. Может быть, у кого-то есть решение этой проблемы или идея, где может быть ошибка. Я просто использую этот пример для простоты. Проект, над которым я работаю, использует ту же структуру. Он также использует службы wcf, и они будут вызываться из неуправляемого C++.
2 ответа
Только что создал небольшой тестовый проект, он работает:
namespace ComTest
{
[Guid("E4435D3B-CBC3-4D41-B4A5-D8116B394195")]
[ClassInterface(ClassInterfaceType.None)]
[ComVisible(true)]
public class Stringconcat_IAMCOM : IStringconcat_IAMCOM
{
public string stringconcat(string a, string b)
{
return a + b;
}
}
[Guid("E130F97E-1844-4C8B-9E57-AF42632A2557")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IStringconcat_IAMCOM
{
[DispId(1)]
string stringconcat(string a, string b);
}
}
И клиент:
#import "C:\Users\rst\Documents\Visual Studio 2008\Projects\ComTest\ComTest\bin\Debug\ComTest.tlb"
#include <iostream>
#include <stdio.h>
#include <windows.h>
using namespace ComTest;
int main(int argc, const char* argv[])
{
HRESULT hr = CoInitialize(NULL);
BSTR a = L" string a ";
BSTR b = L" string b ";
IStringconcat_IAMCOM* q;
hr = CoCreateInstance(__uuidof(Stringconcat_IAMCOM), NULL, CLSCTX_INPROC_SERVER,
__uuidof(IStringconcat_IAMCOM), (void**)&q );
std::cout << q->stringconcat(a, b);
//Uninitialize COM.
CoUninitialize();
return 0;
}
Мое имя сборки ComTest.dll, поэтому я зарегистрировал его, используя:
regasm Comtest.dll /CodeBase
У меня была ошибка в коде C++, ложный вызов CoCreateInstance(...), спасибо, zilog за помощь.
IStringconcat_IAMCOM* q;
hr = CoCreateInstance(__uuidof(Stringconcat_IAMCOM), NULL, CLSCTX_INPROC_SERVER, __uuidof(IStringconcat_IAMCOM), (void**)&q );
И была также ошибка в вызове для службы прокси. Мне пришлось добавить к базовому адресу атрибут конечной точки address="stringconcat". Адрес должен был быть таким:
http://localhost:8000/stringconcatService/stringconcat
И я создаю сервисный прокси теперь так:
[Guid("E4435D3B-CBC3-4D41-B4A5-D8116B394195")]
[ClassInterface(ClassInterfaceType.None)]
[ComVisible(true)]
public class Stringconcat_IAMCOM : IStringconcat_IAMCOM
{
public string stringconcat(string a, string b)
{
EndpointAddress ep = new EndpointAddress("http://localhost:8000/stringconcatService/stringconcat");
proxy = ChannelFactory<IStringconcat>.CreateChannel(new BasicHttpBinding(), ep);
proxy.stringconcat(string a, string b);
}
}
[Guid("E130F97E-1844-4C8B-9E57-AF42632A2557")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IStringconcat_IAMCOM
{
[DispId(1)]
string stringconcat(string a, string b);
}
Теперь я могу звонить из C++ в WCF-сервисы, это здорово!