已解决:在VB6中调用异步方法

问题描述 投票:0回答:1

我在 VB.NET (.NET Framework 4.8) 中制作了一个 dll。
如您所见,该 dll 使用

HttpClient.GetAsync
方法。
如果我在 .NET 应用程序中调用这个 dll,一切都会顺利。
当我构建 dll、创建 tlb 并在 VB6 或 VBA 中调用该方法时,
GetAsync
方法抛出异常:“发生了一个或多个错误”。

我该如何解决这个问题?
我尝试了

Await
关键字,但不起作用。

Private Function CallServer(domain As String) As String
    Dim data As String

    Using client As New HttpClient()
        Try
            Dim response As HttpResponseMessage = client.GetAsync(domain).GetAwaiter.GetResult
            If response.IsSuccessStatusCode Then
                data = response.Content.ReadAsStringAsync().Result
            Else
                data = "HTTPS Request Error: " & response.StatusCode.ToString()
            End If
        Catch ex As Exception
            data = "HTTPS Request Error: " & ex.Message
        End Try
    End Using

    Return data
End Function
Exception Type: System.AggregateException
StackTrace:
    in System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
       in System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
       in System.Threading.Tasks.Task`1.get_Result()
       in ActivationSystem.HttpClientManager.CallServer(String action)

我管理了aggregateException,其中唯一的异常是:
发送请求时发生错误

没有堆栈跟踪。

编辑: 我发现一件事。如果我使用 Albert D. Kallal 示例来调用 google(同样采用 HTTPS 协议),一切都会顺利,但如果我调用我们的域,则会出现错误“发送请求时发生错误”。出现。所以我认为这不是代码问题,而是域问题。但现在的问题是:为什么在 .net 中一切顺利(示例和我的代码、谷歌或我们的域),而在 vba 中则不然?

解决方案: 我用 HTTPWEBRequest 方法解决了问题,下面是正确的代码:

    Function CallServer(domain As String) As String
    ServicePointManager.Expect100Continue = True
    ServicePointManager.SecurityProtocol = DirectCast(3072, SecurityProtocolType)
    ServicePointManager.DefaultConnectionLimit = 9999
    ServicePointManager.ServerCertificateValidationCallback = New Security.RemoteCertificateValidationCallback(AddressOf AcceptAllCertifications)
    Dim request As HttpWebRequest = DirectCast(WebRequest.Create(domain), HttpWebRequest)
    Using response As HttpWebResponse = DirectCast(request.GetResponse(), HttpWebResponse)
        Using stream As Stream = response.GetResponseStream()
            Using reader As New StreamReader(stream)
                Return reader.ReadToEnd()
            End Using
        End Using
    End Using
End Function

Private Function AcceptAllCertifications(sender As Object, certification As System.Security.Cryptography.X509Certificates.X509Certificate, chain As System.Security.Cryptography.X509Certificates.X509Chain, sslPolicyErrors As Security.SslPolicyErrors) As Boolean
    Return True
End Function

我还不知道为什么 HTTPClient 不能与 VB6/VBA 一起使用

vba vb.net async-await vb6
1个回答
0
投票

嗯,你必须在这里使用非异步,因为我不相信 COM 对象支持这样。

但是,请在 vb.net(标准 .net 框架类)中说出这段代码。

Imports System.Net.Http
Imports System.Runtime.InteropServices
Imports System.Threading
<ClassInterface(ClassInterfaceType.AutoDual)>
Public Class WebCallCOM

    Public Function CallServer(domain As String) As String

        Dim data As String
        Using client As New HttpClient()
            Try
                Dim response As HttpResponseMessage = client.GetAsync(domain).GetAwaiter.GetResult
                If response.IsSuccessStatusCode Then
                    data = response.Content.ReadAsStringAsync().Result
                Else
                    data = "HTTPS Request Error: " & response.StatusCode.ToString()
                End If
            Catch ex As Exception
                data = "HTTPS Request Error: " & ex.Message
            End Try
        End Using
        Return data
    End Function

因此,构建上述内容。

现在,在 Access VBA 中,这可以正常工作:

Sub WebLoaderTest()

    Dim cWeb As New WebCallCOM.WebCallCOM
    
    Dim sURL As String
    sURL = "https://Google.ca"
    Dim sResult As String
    
    sResult = cWeb.CallServer(sURL)
    
    Debug.Print sResult
        

End Sub

因此,由于 vb.net 代码未标记为“异步”,因此上述内容对我来说没有错误。

因此,只要该 vb.net 例程未标记为“异步”,那么它就应该等待并工作。

您也许可以在 vb.net 中启动一个全新的线程,也许使用 .join 来完成新线程(而不是任务),然后使用它。

但是,到目前为止,上面发布的代码在用作 VBA 中的 COM 对象时确实工作得很好。

© www.soinside.com 2019 - 2024. All rights reserved.