Jump to content

[Solved] Strange behaviour when running from command line


Recommended Posts

Hi

I've hit a strange issue when doing a HTTP POST call using the WinHTTP COM object in Windows 10.

When I run a script in SCITE (pressing F5 - Run), my script works.

When I run a script with "autoit3.exe myscript.au3" on the windows cmd prompt, it doesn't work - the WinHTTP COM object throws an error stating "the requested action with this object has failed".

However, it gets weird...

If I call $oHTTP.SetRequestHeader("Authorization", "Bearer xoxb-..."), ie with the string directly in the call, it works in both cases.

If I call  $sAuthString = '"Authorization", "Bearer xoxb-..."' (FYI for clarity in this posting, that's a pair of single quotes surrounding the string), followed by...
    $oHTTP.SetRequestHeader($sAuthString), ie with the string in a variable, it only works in SCITE, *not* on the command line.

 

When I MsgBox both versions (direct string vs string variable), it shows both strings looking identical as far as I can tell.

So it seems like, when calling from the command line, the $sAuthString... assignment is somehow mangling the string??

I'm fairly new to AutoIT, so maybe there's something special I need to setup?

TIA

Capture.JPG

Edited by toby9999
Link to post
Share on other sites

I can only guess. Maybe the processes (the autoit.exe and the com proccess) are on the different user level, when ran from the cmd.

Have you tried to start the cmd on the admin mode ?

Quote

Press Windows+R to open the “Run” box. Type “cmd” into the box and then press Ctrl+Shift+Enter to run the command as an administrator

Alternatively, try to set the autoit3.exe to run as admin, as well.

Link to post
Share on other sites
8 hours ago, Dan_555 said:

I can only guess. Maybe the processes (the autoit.exe and the com proccess) are on the different user level, when ran from the cmd.

Have you tried to start the cmd on the admin mode ?

Alternatively, try to set the autoit3.exe to run as admin, as well.

I've just tried all the "run as admin" options but the problem stills persists unfortunately.

Link to post
Share on other sites
11 minutes ago, argumentum said:

you can compile as CUI and ConsoleWrite() or FileWriteLine(). You can get fancier too. For fancier you'll have to look around as there are too many to mention.

I'll give it a go, thanks :)

Link to post
Share on other sites

Can you provide your script with any sensitive parts, like the authorization token, redacted?  There's not enough information to know what the issue is.

Do you not have a COM error handler in your script?  If you do, can you provide the .number, .windescription, .description, and .retcode property values of the error object?

 

Edited by TheXman
Fixed typo
Link to post
Share on other sites
7 minutes ago, TheXman said:

Can you provide your script with any sensitive parts, like the authorization token, redacted?  There's not enough information to know what the issue is.

Do you not have a COM error handler in your script?  If you do, can you provide the .number, .windescription, .description, and .retcode property values of the error object?

 

Will do. I'll add the extra COM error capturing code and get back to you with the results. Thanks.

Link to post
Share on other sites
#include <MsgBoxConstants.au3>

    Local $sOut = ""
    Local $sAuthString = ""
    $oHTTP = ObjCreate("winhttp.winhttprequest.5.1")
    $oHTTP.Open("POST", "https://slack.com/api/chat.postMessage", False)
    $oHTTP.SetRequestHeader("Content-Type", "application/json; charset=utf-8")


    ; OPTION 1: call SetRequestHeader with auth string directly - this works correctly with (a) Running within SCiTE (F5) and (b) Running from cmd prompt (both .exe and "autoit3.exe test.au3")
    $oHTTP.SetRequestHeader("Authorization", "Bearer xoxb-<obfuscated>")

    ; OPTION 2: call SetRequestHeader with auth string in a string variable - this works correctly with (a) Running within SCiTE (F5), BUT DOES NOT WORK with (b) Running from cmd prompt (both .exe and "autoit3.exe test.au3")
    ; When option 2 fails (at the $oHTTP.SetRequestHeader command), the error is "The requested action with this object failed" (see attached image)
    $sAuthString = '"Authorization", "Bearer xoxb-<obfuscated>"'
    $oHTTP.SetRequestHeader($sAuthString)


    $sOut = '{"channel":"#script-notifications", "text":"Test message", "icon_emoji":":information_source:"}'

    $oHTTP.Send($sOut)

    $sStatusCode = $oHTTP.Status
    $sResponse = $oHTTP.ResponseText

    MsgBox($MB_OK,"", "SlackOut: " & @CR & $sOut)
    MsgBox($MB_OK,"", "SlackStatus: " & @CR & $sStatusCode)
    MsgBox($MB_OK,"", "SlackResponse: " & @CR & $sResponse)
56 minutes ago, TheXman said:

Can you provide your script with any sensitive parts, like the authorization token, redacted?  There's not enough information to know what the issue is.

Do you not have a COM error handler in your script?  If you do, can you provide the .number, .windescription, .description, and .retcode property values of the error object?

 

Will do. I'll add the extra COM error capturing code and get back to you with the results. Thanks.

Capture.JPG

Link to post
Share on other sites

First, you do not need to quote the whole prior post.  If you need to quote anything, make it just the relevant parts. 

Your option 2 is incorrect.  The SetRequestHeader method takes 2 parameters, the header name and the header value.  You cannot pass it in a single string like that.  So either stick with option 1 or pass 2 variables, one for the name and one for the value, like:

$sHeaderName  = "Authorization"
$sHeaderValue = "Bearer abc"
$oHTTP.SetRequestHeader($sHeaderName, $sHeaderValue)

Also, you said that option 2 worked when you executed it in scite with F5.  It doesn't work for me so I'm not sure how it worked for you, unless you did it differently than the example that you posted.  :huh2:

 

Other than that, I get back a valid json error response saying my authorization is invalid, which is expected.  I get the same thing whether I run it within scite or from a command line in a cmd console.

Where is your COM error handling?  Actually, where is any error checking at all?  You really should get in the habit of adding error and return checking.  It will make your scripting life much easier.  😀

Edited by TheXman
Link to post
Share on other sites

That's great, it's working now. I had been working on the incorrect assumption that I needed to pass the full string as the header as a SINGLE PARAMETER, including the double quotes and the comma. Whereas your syntax passes TWO parameters to the header.

Thanks so much for your assistance ... I'd probably have been stuck for days searching for an answer otherwise.

Regarding error checking, I do have some basic error checking in the rest of my code (the code I posted here was just an extract of the problem section).

Having said that, I'm actually not sure how to do error checking for the HTTP code because it's calling a COM object, so I can't use AutoIT commands like @error. If you don't mind, could you please point me to some documentation or a script example for that? I very much do want to add some HTTP/COM error checking if possible.

P.S. I snuck a look at your HTTP Server function, and you've given me some good ideas for formatting my code more neatly (I'm very much a noob with AutoIT).

Cheers

Link to post
Share on other sites
7 minutes ago, toby9999 said:

Having said that, I'm actually not sure how to do error checking for the HTTP code because it's calling a COM object, so I can't use AutoIT commands like @error. If you don't mind, could you please point me to some documentation or a script example for that? I very much do want to add some HTTP/COM error checking if possible.

Here's a working example of an HTTP POST with error checking.  If you force errors, like giving it a badly formatted URL or making a COM error  like using .SetHeaders instead of .SetRequestHeader, you will see how the error checking and COM error handler works.

#include <Constants.au3>

http_post_example()

Func http_post_example()
    Const $POST_DATA = '{"fld1": "This is a test string", "fld2": true}'

    Local $oHttp = Null, $oComErr = Null

    ;Register COM Error Handler
    $oComErr = ObjEvent("AutoIt.Error", com_error_handler)
    If @error Then Exit MsgBox($MB_ICONERROR + $MB_TOPMOST, "ERROR", "Unable to register COM error handler - @error = " & @error)

    ;Create HTTP COM object
    $oHttp = ObjCreate("winhttp.winhttprequest.5.1")
    If @error Then Exit MsgBox($MB_ICONERROR + $MB_TOPMOST, "ERROR", "Unable to create HTTP COM object - @error = " & @error)

    With $oHttp
        ;Open POST request, set request header(s), and send the request
        .Open("POST", "https://jsonplaceholder.typicode.com/posts")
        If @error Then Exit MsgBox($MB_ICONERROR + $MB_TOPMOST, "ERROR", StringFormat("(0x%X) %s", $oComErr.RetCode, $oComErr.WinDescription))

        .SetRequestHeader("Content-Type", "application/json")

        .Send($POST_DATA)
        If @error Then Exit MsgBox($MB_ICONERROR + $MB_TOPMOST, "ERROR", StringFormat("(0x%X) %s", $oComErr.RetCode, $oComErr.Description))

        ConsoleWrite(StringFormat("HTTP Status: %s %s", .Status, .StatusText) & @CRLF)

        ;If http status code not 201, exit with message
        If .Status <> 201 Then Exit MsgBox($MB_ICONERROR + $MB_TOPMOST, "ERROR", StringFormat("HTTP Status Code = %s %s", .Status, .StatusText))

        ;Display response
        ConsoleWrite(@CRLF & "HTTP Response:" & @CRLF)
        ConsoleWrite(.ResponseText & @CRLF)
    EndWith
EndFunc

Func com_error_handler($oError)
    With $oError
        ConsoleWrite(@ScriptName & " (" & .scriptline & ") : ==> COM Error intercepted !" & @CRLF)
        ConsoleWrite(@TAB & "Error Number........... " & "0x" & Hex(.number) & @CRLF)
        ConsoleWrite(@TAB & "Error WinDescription... " & StringStripWS(.windescription, $STR_STRIPTRAILING) & @CRLF)
        ConsoleWrite(@TAB & "Error Description...... " & StringStripWS(.description   , $STR_STRIPTRAILING) & @CRLF)
        ConsoleWrite(@TAB & "Error ScriptLine....... " & .scriptline & @CRLF)
        ConsoleWrite(@TAB & "Error RetCode.......... " & "0x" & Hex(.retcode) & @CRLF)
    EndWith

    Return ; Return so @error can be trapped by the calling function
EndFunc

 

Edited by TheXman
Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...