После многочисленных статей в Интернете я создал простую библиотеку классов DLL C#, в которой есть только один метод с именем Add. Он принимает 2 целых числа и возвращает целое число, как показано ниже. Я также зашел в свойства проекта> build> и выбрал опцию «Зарегистрироваться для COM-взаимодействия»:
namespace CSDLL
{
[ComVisible(true)]
public interface IMyClass
{
int Add(int x, int y);
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class MyClass : IMyClass
{
public int Add(int x, int y)
{
return x + y;
}
}
}
Я собрал его успешно (как администратор), и он генерировал файлы CSDLL.dll
и CSDLL.tlb
.
Затем я создал простое консольное приложение на C ++, например:
#include "stdafx.h"
#include <Windows.h>
#import "C:\path\to\my\CSDLL.tlb" no_namespace
int main()
{
CoInitialize(NULL);
IMyClassPtr obj;
obj.CreateInstance(__uuidof(MyClass));
printf("Add result = %d\n", obj->Add(2, 5));
CoUninitialize();
getchar();
return 0;
}
Если я запусту это, я получу ожидаемый результат, напечатанный в окне консоли. Итак, все в порядке.
Затем я изменил свой метод Add
, чтобы вместо добавления 2 целых чисел он вызывал конечную точку SOAP. Я обернул код в try ... catch и я возвращаю 1, если SOAP выполнено так, как я ожидал, 0, если он не вернул то, что я ожидал, и я возвращаю 2 из блока catch, то есть было исключение, подобное Итак:
public int Add()
{
try
{
BasicHttpsBinding binding = new BasicHttpsBinding();
binding.Security.Mode = BasicHttpsSecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
binding.UseDefaultWebProxy = false;
EndpointAddress address = new EndpointAddress(myEndPointString);
// create service myService by passing it binding and endpoint address
// pass necessary parameters to the service
// set ClientCredentials for my service
// get response from the service
MyServiceResponse resp = myService.DoSomething();
if (resp.acknowledged)
{
return 1;
}
else
{
return 0;
}
}
catch (Exception ex)
{
// just return 2 in case of an exception
return 2;
}
}
Если я вызываю эту модифицированную DLL из консольного приложения C ++, она всегда возвращает 2 =, что означает, что какое-то исключение было сгенерировано моим кодом выше. Я нахожусь. NET Framework 4.8.
Однако, если я вызываю его из консольного приложения C#, которое я создал, добавив ссылку на мою C# DLL выше, вызов Add
вернется 1 = означает, что он успешно выполнен с результатом, который я ожидаю получить от него.
Итак, одна и та же C# DLL возвращает 2 разных результата в зависимости от того, вызывается ли она из C ++ или C# Консольного приложения.
После установки некоторых точек останова и отладки моей библиотеки DLL я обнаружил, что при вызове ответа DoSomething
выдается исключение со следующими сообщениями:
Сообщение об исключении: Сообщение = "Произошла ошибка при отправке HTTP-запроса на https://server-address: порт / путь . Это может быть связано с тем, что сертификат сервера не настроен должным образом с HTTP.SYS в случае HTTPS. Это также может быть вызвано несоответствие привязки безопасности между клиентом и сервером. Внутреннее исключительное сообщение: Message = "Аутентификация не удалась, потому что удаленная сторона закрыла транспортный поток."
Почему возникает эта проблема, если DLL вызывается из консольного приложения C ++, а не в том случае, если та же DLL вызывается из консольного приложения C#? Она должна что-то делать с безопасностью, я полагаю, что оба будут работать нормально, если вызывается простой математический метод Add
, но если вызывается метод, SOAP запрашивающий, консольное приложение C# будет работать нормально, тогда как консольное приложение C ++ вызовет в DLL исключение?