[英]C# DLL Calling SOAP Web Service From C++ App
Following numerous articles online, I created a simple C# DLL Class Library that has just one method called Add.根据在线的大量文章,我创建了一个简单的 C# DLL 类库,它只有一个名为 Add 的方法。 It accepts 2 integers and returns an integer like below.
它接受 2 个整数并返回一个如下所示的整数。 I also went to project properties > build > and selected "Register for COM interop" option:
我还转到了项目属性 > 构建 > 并选择了“注册 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;
}
}
}
I built it successfully (as admin) and it generated CSDLL.dll
and CSDLL.tlb
files.我成功构建了它(以管理员身份)并生成了
CSDLL.dll
和CSDLL.tlb
文件。
Next I created a simple C++ console app like so:接下来我创建了一个简单的 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;
}
If I run this, I get expected result printed on console window.如果我运行它,我会在控制台窗口上打印出预期的结果。 So, that is all fine.
所以,这一切都很好。
Next I modified my Add
method so that instead of adding 2 integers, it calls a SOAP endpoint.接下来,我修改了我的
Add
方法,以便它调用 SOAP 端点而不是添加 2 个整数。 I wrapped the code in try...catch and I return 1 if SOAP executed as I would expect, 0 if it did not return what I expect, and I return 2 from within a catch block, meaning there was an exception like so:我将代码包装在 try...catch 中,如果 SOAP 按我的预期执行,则返回 1,如果没有返回我期望的内容,则返回 0,并且我从 catch 块中返回 2,这意味着存在如下异常:
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;
}
}
If I call this modified DLL from a C++ console application, it always return 2 = meaning some exception was thrown and cought by my code above.如果我从 C++ 控制台应用程序调用这个修改后的 DLL,它总是返回 2 = 意味着我上面的代码抛出并咳嗽了一些异常。 I am on .NET Framework 4.8.
我在 .NET Framework 4.8 上。
However, if I call it from a C# console application which I created by adding reference to my C# DLL above, the call to Add
returns 1 = meaning it executed successfully with result I would expect to get from it.但是,如果我从通过添加对上面的 C# DLL 的引用创建的 C# 控制台应用程序调用它,则对
Add
的调用返回 1 = 表示它成功执行并得到我期望从中获得的结果。
So, the same C# DLL returns 2 different results depending whether it is called from C++ or C# Console application.因此,同一个 C# DLL 返回 2 个不同的结果,具体取决于它是从 C++ 还是 C# 控制台应用程序调用。
After setting some breakpoints and debugging my DLL, I found that the call to DoSomething
response is throwing exception with following messages:在设置了一些断点并调试了我的 DLL 后,我发现对
DoSomething
响应的调用抛出异常并显示以下消息:
Exception Message: Message = "An error occurred while making the HTTP request to https://server-address:port/path . This could be due to the fact that the server certificate is not configured properly with HTTP.SYS in the HTTPS case. This could also be caused by a mismatch of the security binding between the client and the server. Inner Exception Message: Message = "Authentication failed because the remote party has closed the transport stream."异常消息:消息 =“向https://server-address:port/path发出 HTTP 请求时出错。这可能是由于在 HTTPS 情况下未使用 HTTP.SYS 正确配置服务器证书. 这也可能是由于客户端和服务器之间的安全绑定不匹配造成的。内部异常消息:消息 =“身份验证失败,因为远程方已关闭传输流。”
Why is it having this issue if the DLL is called from a C++ console app and not if the same DLL is called from a C# console app?如果从 C++ 控制台应用程序调用 DLL 而不是从 C# 控制台应用程序调用相同的 DLL,为什么会出现此问题? It has to do something with security I guess as both will execute just fine if calling simple math
Add
method but if calling a method that does SOAP request, the C# console app will execute just fine whereas C++ console app will cause the DLL to throw exception?我猜它必须与安全有关,因为如果调用简单的 math
Add
方法,两者都会执行得很好,但是如果调用执行 SOAP 请求的方法,C# 控制台应用程序将执行得很好,而 C++ 控制台应用程序将导致 DLL 抛出异常?
After lots of reading, it turns out the reason for this was that SecurityProtocol
gets set to different SecurityProtocolType
if the C# DLL is called from a C# vs C++ application.经过大量阅读,事实证明这是因为如果从 C# 与 C++ 应用程序调用 C# DLL,则
SecurityProtocol
将设置为不同的SecurityProtocolType
。
In order to resolve, I had to set SecurityProtocol
like below before making any request:为了解决这个问题,我必须在提出任何请求之前像下面这样设置
SecurityProtocol
:
if (ServicePointManager.SecurityProtocol == (SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls))
{
// This was crucial to do to make web service call work when C# DLL is called
// from a C++ app. It turns out that if webservice call is made:
// 1) from C# console app calling C# DLL that makes web service call,
// the SecurityProtocol is set to TLS | TLS11 | TLS12 | TLS13
// 2) from C++ console app calling C# DLL that makes web service call,
// the SecurityProtocol is set to SSL3 | TLS
// In case of 2) above, the call would throw exception as explained above
// whereas 1) would work just fine.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
| SecurityProtocolType.Tls11
| SecurityProtocolType.Tls12;
// TLS13 was not available for some reason, so did not set it here
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.