2

I am using the code from Mark Bertenshaw's post: VB6 -- using POST & GET from URL and displaying in VB6 Form

On 32 Bit development machine Mark's code works fine. But on my 64 Bit machine it Gives an out of memory error at the code:

m_sOutput = StrConv(AsyncProp.Value, vbUnicode)

The returned data from the http request is very simple {"response": 2}, or {"response": 6} etc.

On the 32bit machine it is loading scrrun.dll from system32 folder but on 64bit machine it is loading from sysWOW64 folder (in the references).

Is it that that is causing the issue as I think the Memory error message is a red herring?

User Control (HTTPService)

Option Explicit

Private Const m_ksProperty_Default              As String = ""

Private m_sHost                                 As String
Private m_nPort                                 As Long
Private m_sPath                                 As String
Private m_dctQueryStringParameters              As Scripting.Dictionary

Private m_sOutput                               As String

' Ensure that all parts of the query string are deleted.
Public Sub ClearQueryString()

    Set m_dctQueryStringParameters = New Scripting.Dictionary

End Sub

' Executes "GET" method for URL.
Public Function Get_() As String

    ' Read in data from URL. UserControl_AsyncReadComplete will fire when finished.
    UserControl.AsyncRead "http://" & m_sHost & ":" & CStr(m_nPort) & "" & m_sPath & "?" & GetQueryString(), vbAsyncTypeByteArray, m_ksProperty_Default, vbAsyncReadSynchronousDownload

    ' Return the contents of the buffer.
    Get_ = m_sOutput

    ' Clear down state.
    m_sOutput = vbNullString

End Function

' Returns query string based on dictionary.
Private Function GetQueryString() As String

    Dim vName                                   As Variant
    Dim sQueryString                            As String

    For Each vName In m_dctQueryStringParameters
        sQueryString = sQueryString & CStr(vName) & "=" & m_dctQueryStringParameters.Item(vName) & "&"
    Next vName

    GetQueryString = Left$(sQueryString, Len(sQueryString) - 1)

End Function

' Sets the remote host.
Public Property Let Host(ByVal the_sValue As String)

    m_sHost = the_sValue

End Property

' Sets the directory and filename part of the URL.
Public Property Let Path(ByVal the_sValue As String)

    m_sPath = the_sValue

End Property

' Sets the port number for this request.
Public Property Let Port(ByVal the_nValue As Long)

    m_nPort = the_nValue

End Property

' Sets a name/value pair in the query string. Supports duplicate names.
Public Property Let QueryStringParameter(ByVal the_sName As String, ByVal the_sValue As String)

    m_dctQueryStringParameters.Item(the_sName) = the_sValue

End Property

' Fired when the download is complete.
Private Sub UserControl_AsyncReadComplete(AsyncProp As AsyncProperty)

    ' Gets the data from the internet transfer.
    m_sOutput = StrConv(AsyncProp.Value, vbUnicode)
End Sub

Private Sub UserControl_Initialize()

    ' Initialises the scripting dictionary.
    Set m_dctQueryStringParameters = New Scripting.Dictionary

End Sub

Calling it from:

Button Code

Private Sub cmdCheckNow_Click()
On Error GoTo err_trap
Call hideCheckNow
QProGIF1.Visible = True
Call DeleteUrlCacheEntry("http://mysite.co.uk/mobicleanud/chkupdates.php")

DoEvents
HttpService.Host = "mysite.co.uk"
HttpService.Port = 80
HttpService.Path = "/thefolder/chkupdates.php"
HttpService.QueryStringParameter("license") = licensekey
HttpService.QueryStringParameter("vers") = "SOFTWARE2"
HttpService.QueryStringParameter("appmajor") = App.Major
HttpService.QueryStringParameter("appminor") = App.Minor
HttpService.QueryStringParameter("apprevis") = App.Revision

txtOutput.Text = HttpService.Get_

If txtOutput.Text = "" Or IsNull(txtOutput.Text) Or txtOutput.Text = "({" & Chr(34) & "response" & Chr(34) & ":" & "9" & "})" Then
        frmError.lblErrorMessage.Caption = "Licensing Server cannot validate the License Number! Error (9) - Please try again."
        frmError.Show vbModal
        Call showCheckNow
        QProGIF1.Visible = False

        DoEvents
        Exit Sub
End If
If txtOutput.Text = "" Or IsNull(txtOutput.Text) Or txtOutput.Text = "({" & Chr(34) & "response" & Chr(34) & ":" & "8" & "})" Then
        frmError.lblErrorMessage.Caption = "Licensing Server cannot validate the License Number! Error (8) - Please try again."
        frmError.Show vbModal
        Call showCheckNow
        QProGIF1.Visible = False

        DoEvents
        Exit Sub
End If
If txtOutput.Text = "" Or IsNull(txtOutput.Text) Or txtOutput.Text = "({" & Chr(34) & "response" & Chr(34) & ":" & "7" & "})" Then
        frmError.lblErrorMessage.Caption = "Licensing Server cannot validate the License Number! Error (7) - Please try again."
        frmError.Show vbModal
        Call showCheckNow
        QProGIF1.Visible = False

        DoEvents
        Exit Sub
End If
If txtOutput.Text = "" Or IsNull(txtOutput.Text) Or txtOutput.Text = "({" & Chr(34) & "response" & Chr(34) & ":" & "6" & "})" Then
        frmError.lblErrorMessage.Caption = "Licensing Server cannot validate the License Number! Error (6) - Please try again."
        frmError.Show vbModal
        Call showCheckNow
        QProGIF1.Visible = False

        DoEvents
        Exit Sub
End If
QProGIF1.Visible = False
If txtOutput.Text = "({" & Chr(34) & "response" & Chr(34) & ":" & "2" & "})" Then
        lblchecked.Caption = "Your License was validated and there is a new version of Mobiclean Pro available to Download and Install."
        lblchecked.Visible = True
        QProGIF1.Visible = False

        DoEvents
        cmdGet.Visible = True
        Exit Sub
End If
If txtOutput.Text = "({" & Chr(34) & "response" & Chr(34) & ":" & "3" & "})" Then
        lblchecked.Caption = "Your License was validated. You have the latest version of Mobiclean Pro - No Update available."
        lblchecked.Visible = True
        QProGIF1.Visible = False

        DoEvents
        Exit Sub
End If
exit_sub:

  Exit Sub

err_trap:
        frmError.lblErrorMessage.Caption = "An error has occurred - Code: " & Err.Number & " Description: " & Err.description
        frmError.Show vbModal
    Resume exit_sub
End Sub

Just can't find what is causing the issue.

Error Message is

Out of Memory

If built on On 64Bit Win 10

No error message if built on 32Bit win 10 and reads file and continues no problem

Cœur
  • 37,241
  • 25
  • 195
  • 267
  • Can you narrow down the cause of the error a bit further? Is it StrConv() failing itself, or does it fail to get the .Value property? – StayOnTarget Jun 17 '19 at 11:33
  • `.Value` should return a byte array because of the `vbAsyncTypeByteArray`. `StrConv(vbUnicode)` on a byte array is only correct when the byte array contains text in the [codepage for non-Unicode programs](https://stackoverflow.com/questions/6552310/how-can-i-get-the-charset-vb6-is-using/6552368#comment7727500_6552368) of the current computer. Most likely that it will contain UTF-8 instead, so calling `vbUnicode` on it is certainly wrong. To correctly convert a byte array to Unicode text, use [MultiByteToWideChar](https://stackoverflow.com/a/23980044/11683). – GSerg Jun 17 '19 at 11:37
  • Thank you @Dave, yes you were correct it was the StrConv failing to convert the string if it was empty (which it shouldn't have been). I have now added code to handle that and all is good. Still not sure why it worked on 32Bit machine but not 64Bit machine. – Steve Riches Jun 17 '19 at 12:41
  • @SteveRiches You are correct, `StrConv` raises error 7 when provided with a `Variant` that contains an [uninitialized](https://stackoverflow.com/q/183353/11683) array. It does not raise the error if the array is passed without the `Variant` wrapper. However I see this behaviour on both x86 and x64 Windows. – GSerg Jun 17 '19 at 12:58
  • About the System32/SysWOW64 folder: that is completely normal and expected behavior. VB6 programs are always 32-bit. Despite the names, the System32 folder in a 64-bit machine has 64-bit DLLs, while the SysWOW64 holds the 32-bit versions. There are compatibility layers in Windows that fake things so that when a 32-bit program asks for System32 they get SysWOW64 instead. The folder names are terribly confusing, but this scheme was found to cause the least amount of compatibility problems. – Euro Micelli Jun 21 '19 at 12:17

0 Answers0