我在 VB.NET (.NET Framework 4.8) 中制作了一个 dll。
如您所见,该 dll 使用
HttpClient.GetAsync
方法。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 一起使用
嗯,你必须在这里使用非异步,因为我不相信 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 对象时确实工作得很好。