从C ++应用程序调用C#DLL调用SOAP Web服务

像素点

在网上浏览了无数文章之后,我创建了一个简单的C#DLL类库,其中只有一种称为Add的方法。它接受2个整数,并返回如下所示的整数。我还转到项目属性>构建>,然后选择“注册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;
        }
    }
}

我内置它成功(如admin)和它产生CSDLL.dllCSDLL.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中,如果按照我的期望执行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#控制台应用程序调用它,则对Addreturn 1 =的调用意味着它已成功执行,并期望从中获得结果。

因此,相同的C#DLL返回2个不同的结果,具体取决于是从C ++还是C#控制台应用程序调用它。

在设置了一些断点并调试了我的DLL之后,我发现对DoSomething响应的调用引发异常并显示以下消息:

异常消息:消息=“向https:// server-address:port / path发出HTTP请求时发生错误。这可能是由于在HTTPS情况下未使用HTTP.SYS正确配置服务器证书的事实内部异常消息:消息=“由于远程方已关闭传输流,所以身份验证失败。”内部客户端消息和服务器之间的安全绑定不匹配。

如果从C ++控制台应用程序调用DLL,而不是从C#控制台应用程序调用相同的DLL,为什么会出现此问题?我想它必须做些安全性,因为如果调用简单的数学Add方法,两者都将执行得很好,但是如果调用执行SOAP请求的方法,则C#控制台应用程序将执行得很好,而C ++控制台应用程序将导致DLL引发异常?

像素点

经过大量阅读后,事实证明,如果从C#vs C ++应用程序调用C#DLL ,则会将其SecurityProtocol设置为不同SecurityProtocolType

为了解决这个问题,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
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章