3

for a project I'm working on I'm attempting to do a Asynchronous XMLHTTP Call. I'm using the following code:

soapmessage = _
"<?xml version='1.0' encoding='utf-8'?>"& vbcrlf& vbcrlf & _
"<soap:Envelope"& vbcrlf & _
" xmlns:xsi="&chr(34)&"http://www.w3.org/2001/XMLSchema-instance"&chr(34)& 
vbcrlf & _
" xmlns:xsd="&chr(34)&"http://www.w3.org/2001/XMLSchema"&chr(34)& vbcrlf & _
" xmlns:soap="&chr(34)&"http://www.w3.org/2003/05/soap-
envelope"&chr(34)&">"& vbcrlf & _
" <soap:Body>"& vbcrlf & _
"<notification>"& vbcrlf & _
"   <action>Action</action>"& vbcrlf & _
"   <objectid>333333</objectid>"& vbcrlf & _
"</notification>"& vbcrlf & _
" </soap:Body>" & vbcrlf & _
" </soap:Envelope>"

strEndpoint = "**********"

Set xmlhttp = CreateObject("MSXML2.SERVERXMLHTTP.6.0")
xmlhttp.open "POST", strEndpoint, True
xmlhttp.OnReadyStateChange = doHttpOnReadyStateChange()
xmlhttp.setRequestHeader "Content-Type", "text/xml; charset=utf-8"
xmlhttp.Send soapmessage

Function doHttpOnReadyStateChange()
    If xmlhttp.ReadyState = 4 Then
        'do something
    End If
End Function

When I try to execute this I get the following:

test.vbs(19, 1) Microsoft VBScript runtime error: Type mismatch: 'xmlhttp.OnReadyStateChange'

any idea what I could be doing wrong? It's my first time trying an async call so i'm a bit puzzled with the OnReadyStateChange

user692942
  • 16,398
  • 7
  • 76
  • 175
Dirk R.
  • 171
  • 1
  • 13

1 Answers1

2

It needs a function reference which you can get using the GetRef() function.

xmlhttp.OnReadyStateChange = GetRef("doHttpOnReadyStateChange")

Dirk.R: Would like to add that while this is the fix. Keep in mind that the order of the statements also matters!

Dirk R.
  • 171
  • 1
  • 13
user692942
  • 16,398
  • 7
  • 76
  • 175
  • Tried it with the GetRef("") arround the functionname. No more error but also nothing happens.. Put some debug code in there to get a msgbox or anything but never seems to enter the function (even outside the "if").. – Dirk R. May 12 '17 at 17:16
  • @DirkR. strange, have you tried a `Sub` procedure instead of a `Function` as your not returning anything, can't see it making a difference though. It's almost like the `OnReadyStateChange` event isn't firing. – user692942 May 12 '17 at 17:23
  • Just tried with a Sub, but same outcome.. It does seem like it's not fireing. I tried using a regular MSXML2.XMLHTTP.6.0 object instead of the server one but also nothing.. really stumped here! – Dirk R. May 12 '17 at 17:30
  • Ok some more progress, I changed the order of the statements and put the xmlhttp.OnreadyStateChange = GetRef("") before the .Open and now it seems to fire! However, it only fires a single time and return "1" – Dirk R. May 12 '17 at 17:33
  • 1
    @DirkR. because it's ASync the `Send()` method will return straight away, ending the script, so the next callback never has chance to run. You'll need to use `WScript.Sleep()` or something to keep the script running. – user692942 May 12 '17 at 17:46
  • That makes sense but also defeats the purpose of why I'm calling it async. I have a 2nd script being called (as a response to receiving my call) that comes in wait till I get my http 200 for my initial call. That http 200 however is only responded when the 2nd script can execute which it cannot since it's in the queue behind the first still waiting.. So either I make it synchronous and it just times out due to a deadlock or I make it a sync and I can never get the response? Something doesn't seem right here. Do you have an example of how I should implement the sleep? Now it just hangs – Dirk R. May 12 '17 at 18:00
  • @DirkR. to be honest I've never done an async http call in VBScript, I'm not sure you can to be honest, I'd just use the blocking approach and call the second script on the first scripts completion. I've never had a situation where I've needed to use ASync in a script, end of the day if the first calls response is important to the second call, blocking seems the best approach. – user692942 May 12 '17 at 18:15
  • That would be my first choice but unfortunatly the completion of the first script depends on the outcome of the 2nd script and they both run on the same system. (that's why they deadlock eachother in the queue). Feels like the only solution will be to ofload the first script to a simple command shell and capture the std_out of it. – Dirk R. May 12 '17 at 18:19
  • @DirkR. Why do they run independently? Surely if the second script is dependent on the first, the first script should initialise the second...sounds like an architecture issue if I'm honest. – user692942 May 12 '17 at 18:22
  • Well Script 1 on system A sends the call (a notification) to system B. That triggers Script 2 which calls system A again to retrieve data. Script 2 however only sends a response on the notification call once it has retrieved it's data. Since Script 1 suspends all action on System A (synchronous) Script 2 can never retrieve it's data from System A and a timeout occurs on Script 1. For me that too is a issue with Script 2 but I'm not in charge of thatone :) – Dirk R. May 12 '17 at 18:28
  • @DirkR. Classic deadlock, unfortunately I'm not sure what to suggest. My original answer was just helping fix the `Type mismatch` error, I honestly can't see how that setup would work using scripting. Sorry I can't be more help. – user692942 May 12 '17 at 18:41
  • 1
    Well you fixed the original question! VBScript just has a strange implementation of the SERVERXMLHTTP object i guess that supports async but not really. Thanks for the assistance! – Dirk R. May 12 '17 at 19:08