在网上阅读了许多文章后,我创建了一个简单的C# DLL类库,其中只有一个名为Add的方法。它接受两个整数并返回一个整数,如下所示。我还进入了项目属性>生成>并选择了“注册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
方法,使其不是添加两个整数,而是调用一个SOAP端点。我将代码包装在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;
}
}
如果我从C++控制台应用程序中调用这个修改过的DLL,它总是返回2 = 意味着某个异常被抛出并被我的代码捕获。我使用的是.NET Framework 4.8。
然而,如果我从一个添加了对上述C# DLL引用的C#控制台应用程序中调用它,调用
Add会返回1 = 意味着它成功执行并得到我期望得到的结果。
因此,同一个C# DLL返回2种不同的结果,具体取决于它是从C++还是C#控制台应用程序中调用的。
在设置一些断点和调试我的DLL后,我发现对DoSomething
的调用响应会抛出以下消息的异常:
异常消息:
Message =“在进行HTTP请求https://server-address:port/path时发生错误。这可能是由于服务器证书在HTTPS情况下没有正确配置HTTP.SYS造成的。这也可能是由于客户端和服务器之间的安全绑定不匹配。
内部异常消息:
Message =“由于远程方关闭了传输流,所以身份验证失败。”
如果从C++控制台应用程序中调用DLL,为什么会出现这个问题,而从C#控制台应用程序中调用相同的DLL却不会出现这个问题?我猜这与安全有关,因为如果调用简单的数学Add方法,则两者都将执行得很好,但如果调用执行SOAP请求的方法,则C#控制台应用程序将执行得很好,而C++控制台应用程序将导致DLL抛出异常。
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; | (SecurityProtocolType)12288; // Tls13;
- Gerald