wqweto / VbAsyncSocket

Sockets with pure VB6 impl of TLS encryption
MIT License
164 stars 31 forks source link

VB6 App : Runtime error on Win 10 22H2 on Macbook using Boot Camp #36

Open CouinCouin opened 8 months ago

CouinCouin commented 8 months ago

Hi,

A user reported me a problem with check update function of my software using HttpRequest class, so I made a small app with just this : cAsyncSocket.cls cHttpRequest.cls cTlsSocket.cls mdTlsThunks.bas

Project with a Form, a Command button, a WebBrowser. Code :

Private Sub Command1_Click()
    CheckUpdate ("https://mydomaind.com/checkupdate.php")
End Sub

Private Sub CheckUpdate(ByVal Url As String)

    Dim req As New cHttpRequest
    Dim resp As String

    With req
        .SetTimeouts 500, 500, 500, 500
        .Open_ "POST", Url, False
        .SetRequestHeader "Content-Type", "application/json"
        .Option_(WinHttpRequestOption_SslErrorIgnoreFlags) = 13056 '&H3300
        .Send
        If .ResponseText <> "" Then
            MsgBox .ResponseText
            WebBrowser1.navigate "about:blank"
            DoEvents
            WebBrowser1.document.Write .ResponseText
        End If
    End With
    Set req = Nothing

End Sub

When the user clicks on Command1 button, he get only Run-time error -2147012894 (80072ee2) . The only info I found with google, was timeout problem, so I increased timeouts from 500 to 1000, but the user has tested with the same result.

Any idea ? :)

Thanks Couin

wqweto commented 8 months ago

https://mydomaind.com/checkupdate.php is not a valid domain.

Tell me the real URL you are having problems with so I can test here.

CouinCouin commented 8 months ago

Hi Vladimir :)

I think it's not an URL problem but only with Windows on Mac with bootcamp, as well as on any other machine (Laptop with Win 10, my PC with Win 10, Win XP and 10 virtual machines, it's always OK.

Here is the real URL : https://jinglepalettereloaded.com/checkupdate.php?lastver

wqweto commented 8 months ago

Does it work with WinHttpRequest?

Does it work with IP address directly (https://217.160.0.76/checkupdate.php?lastver)?

CouinCouin commented 8 months ago

Hi, I will built an app to test with WinhttpRequest and give it to the user so he will test. About the URLwith IP, as well as the server is not dedicated, it is unreachable with IP.

CouinCouin commented 8 months ago

Hi Vladimir :)

I built 4 tests and the user tested them:

With WinhttpRequest:

With chttpRequest:

wqweto commented 8 months ago

When the user clicks on Command1 button, he get only Run-time error -2147012894 (80072ee2) .

Can you pinpoint which line in your code exactly raises this error? Do you have req_OnError event implemented?

The only info I found with google, was timeout problem, so I increased timeouts from 500 to 1000, but the user has tested with the same result.

You can skip calling req.SetTimeouts method so that it uses default timeouts like WinHttpRequest, which are 15-30 seconds.

Which version of Http Request Replacement DLL do you use? Latest is 1.0.5

Edit: So you are using class sources directly, not the compiled DLL.

CouinCouin commented 8 months ago

Hi :)

I implented "On Error Goto ..." so should have more infos, I added a checkbox to test with and without setTimeouts method, here is the code:

Public STO As Boolean

Private Sub Form_Load()
    STO = False
    WebBrowser1.navigate "about:blank"
End Sub

Private Sub Command1_Click()
    CheckHTTPc "Check 1", "https://jinglepalettereloaded.com/checkupdate.php?lastver"
End Sub

Private Sub Check1_Click()
    If Check1.Value = vbChecked Then
        STO = True
    Else
        STO = False
    End If
End Sub

Private Function CheckHTTPc(ByVal Butt As String, ByVal Url As String) As String
    On Error GoTo Exit_Routine

    Dim req As New cHttpRequest

    WebBrowser1.navigate "about:blank"

    With req
        If STO = True Then .SetTimeouts 500, 500, 500, 500     ' ResolveTimeout, ConnectTimeout, SendTimeout, ReceiveTimeout
        .Open_ "POST", Url, False
        .Option_(WinHttpRequestOption_SslErrorIgnoreFlags) = 13056 '&H3300
        .Send
        If .ResponseText <> "" Then
            DoEvents
            WebBrowser1.document.Write Butt & "<br>" & .ResponseText
            Else
            DoEvents
            WebBrowser1.document.Write Butt & "<br>" & "Error when trying to reach URL "
        End If

    End With
    Set req = Nothing

Exit Function
Exit_Routine:
MsgBox Butt & vbCrLf & "Error when trying to reach URL" & _
vbCrLf & "Error source:" & Err.Source & _
vbCrLf & "Error number:" & Err.Number & _
vbCrLf & "Error description:" & Err.Description
Exit Function
End Function

About the last version, I use class source, yes. I encountered problems when I replaced files I already have, for last ones, I got errors on modules can not be loaded, continue ? yes/no, I tried to re-add them but Class Modules was seen as Modules (so getting a lot of red lines in VB6 IDE), but I just tried to remove Modules and Class Modules from VB6 IDE, and re-add them and now it looks good.

I compiled the exe and sent to my user. Just having to wait its report.

CouinCouin commented 8 months ago

Re, Without seTimeouts, my user got the result in around 3 seconds. Browsing the URL with Edge was fast. With SetTimeouts, he got the error.

ErrorLog

Also, a VB6 app still running before timeout ? I mean, if the user get the result in 3 seconds, is the app will do nothing else during this delay ? Or http request are executed separatly from the rest of the app ?

wqweto commented 8 months ago

With SetTimeouts, he got the error.

It probably needs time to resolve host name through his DNS server. I usually set timeouts to ~5 seconds while the defaults are ~15 seconds for resolve and ~30 seconds for send/receive (as used by WinHttpRequest).

Also, a VB6 app still running before timeout ?

This depends on Open third parameter Async -- if True the operation is executed in the background and you get notified through events like OnError, OnResponseFinished and OnResponseDataAvailable.

In asynchronous mode you can use WaitForResponse method too which will block until response (or error) is received.

Overall using synchronous execution (the way you have it done) is much more easier to implement but might stall the program if timeouts are hit in cases of lost connectivity, slow DNS servers, etc.

CouinCouin commented 8 months ago

Hi :) About host name resolution time, are toy talking about just with cHttpRequest or in general ? Because my user tells me that ther same URL in Edge answers fast.

Oh thanks for explanation of Async mode, so as well as I would not block the app while trying to reach the page (for multiple reason, machine has no internet connexion, etc etc), so I should change for this? : .Open_ "POST", Url, True

wqweto commented 8 months ago

so I should change for this? : .Open_ "POST", Url, True

Yes, this is the same model as in WinHttpRequest. The result is available in OnResponseFinished event but first you have to declare req variable WithEvents so that you can receive events from the instance at all. This variable has to be a member variable of a form or a class too, not local variable for the procedure.

This will allow you to use "normal" timeouts because half a second is not enough for name resolution or establishing a connection in the general case.

Because my user tells me that ther same URL in Edge answers fast.

Is this Edge running under the virtual machine (i.e. Boot Camp) too or is it native for the Mac OS?

CouinCouin commented 8 months ago

Hi Vladimir :)

He should talking about Egde in Windows. I don't know BootCamp (I have no Mac) but after some search, it looks more a dual boot menu (to choose to boot with Mac OS or Windows) on startup.

Thanks for tip about events :) After some search, I created a small exe with just a Form with this code:

Option Explicit

Private WithEvents http As cHttpRequest

Private Sub Command1_Click()
Set http = New cHttpRequest
http.Open_ "POST", "https://jinglepalettereloaded.com/checkupdate.php?lastver", True
http.Send
End Sub

Private Sub http_OnResponseFinished()
MsgBox http.ResponseText
End Sub

But as well as in the final project, httprequest should not be related to a form, I try to move the http variable and http_OnResponseFinished sub to a Class module, the project does not run anymore (variable not defined, even setting as Public instead of Private). I get difficulties to find good Class module examples to create a class from this code :(