Anyone know what I need to do to get this to work in AHKv2? (64-bit)
Specifically, I am trying to use this to send a file over HTTP, based on
BlackHolyMan's example in this thread.
Running into this error (in BinArr.ahk)
Code: Select all
Error in #include file "...\BinArr.ahk":
0x800A0BB9 -
Source: ADODB.Stream
Description: Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another.
HelpFile: C:\WINDOWS\HELP\ADO270.CHM
HelpContext: 1240641
Specifically: Write
Line#
024: }
026: {
027: oADO := ComObjCreate("ADODB.Stream")
029: oADO.Type := 1
030: oADO.Mode := 3
031: oADO.Open
032: For i,arr in Arrays
---> 033: oADO.Write(arr)
034: oADO.Position := 0
035: Return,oADO.Read, oADO.Close
036: }
038: {
039: oADO := ComObjCreate("ADODB.Stream")
041: oADO.Type := 1
042: oADO.Mode := 3
Continue running the script?
I spent some time debugging but can't really figure out the problem. The BinArr_ functions seem to be working okay but I don't fully understand it (the ADO stream is working correctly I think: I can read size, position, etc, and it returns an object, which I assume is a binary object)
Seems like BinArr also causes problems for some other people. See
here and
here. Not sure if they had the same problem. Maybe I should try the alternative they suggest?
My code (BlackHolyMan's code with double-quote escaping updated to work for AHKv2)
Code: Select all
#Include %A_ScriptDir%\CreateFormData.ahk ; https://gist.github.com/tmplinshi/8428a280bba58d25ef0b
#Include %A_ScriptDir%\BinArr.ahk ; https://gist.github.com/tmplinshi/a97d9a99b9aa5a65fd20
#Include %A_ScriptDir%\Jxon.ahk ; https://github.com/cocobelgica/AutoHotkey-JSON/blob/master/JSON.ahk
image_path := "C:\Xerxes.png"
PB_Token := "<will need to use your own PushBullet token to test this>"
PB_Image_Name := "Xerxes.png"
JSON_Response := PB_PushUpload_request(PB_Token, PB_Image_Name)
JSON_Response_object := Jxon_Load( JSON_Response )
objParam := { "file": [image_path]}
CreateFormData(postData, hdr_ContentType, objParam)
Status := PB_PushUpload_formData(JSON_Response_object.upload_url, postData, hdr_ContentType)
if (Status != 204)
{
msgbox % "Upload Error!"
return
}
msgbox % PB_PushFile(PB_Token, "This is an image test", JSON_Response_object.file_name, JSON_Response_object.file_type, JSON_Response_object.file_url)
return
PB_PushUpload_request(PB_Token, PB_Image_Name)
{
WinHTTP := ComObjCreate("WinHTTP.WinHttpRequest.5.1")
WinHTTP.SetProxy(0)
WinHTTP.Open("POST", "https://api.pushbullet.com/v2/upload-request", 0)
WinHTTP.SetCredentials(PB_Token, "", 0)
WinHTTP.SetRequestHeader("Content-Type", "application/json")
PB_Body := "{`"file_name`": `"" PB_Image_Name "`", `"file_type`": `"image/png`"}"
WinHTTP.Send(PB_Body)
Result := WinHTTP.ResponseText
Status := WinHTTP.Status
return Result
}
PB_PushUpload_formData(PB_upload_url, PB_postData, PB_ContentType)
{
WinHTTP := ComObjCreate("WinHttp.WinHttpRequest.5.1")
WinHTTP.Open("POST", PB_upload_url, true)
WinHTTP.SetRequestHeader("Content-Type", PB_ContentType)
WinHTTP.Option(6) := False ; No auto redirect
WinHTTP.Send(PB_postData)
WinHTTP.WaitForResponse()
Result := WinHTTP.ResponseText
Status := WinHTTP.Status
return Status
}
PB_PushFile(PB_Token, PB_Body, PB_file_name, PB_file_type, PB_file_url)
{
WinHTTP := ComObjCreate("WinHTTP.WinHttpRequest.5.1")
WinHTTP.SetProxy(0)
WinHTTP.Open("POST", "https://api.pushbullet.com/v2/pushes", 0)
WinHTTP.SetCredentials(PB_Token, "", 0)
WinHTTP.SetRequestHeader("Content-Type", "application/json")
PB_Body := "{`"type`": `"file`", `"body`": `"" PB_Body "`", `"file_name`": `"" PB_file_name "`", `"file_type`": `"" PB_file_type "`", `"file_url`": `"" PB_file_url "`"}"
WinHTTP.Send(PB_Body)
Result := WinHTTP.ResponseText
Status := WinHTTP.Status
return Status
}
CreateFormData.ahk (only updated double-quote escaping for AHKv2 compatibility)
Code: Select all
/*
CreateFormData - Creates "multipart/form-data" for http post
Usage: CreateFormData(ByRef retData, ByRef retHeader, objParam)
retData - (out) Data used for HTTP POST.
retHeader - (out) Content-Type header used for HTTP POST.
objParam - (in) An object defines the form parameters.
To specify files, use array as the value. Example:
objParam := { "key1": "value1"
, "upload[]": ["1.png", "2.png"] }
Requirement: BinArr.ahk -- https://gist.github.com/tmplinshi/a97d9a99b9aa5a65fd20
Version : 1.20 / 2016-6-17 - Added CreateFormData_WinInet(), which can be used for VxE's HTTPRequest().
1.10 / 2015-6-23 - Fixed a bug
1.00 / 2015-5-14
*/
; Used for WinHttp.WinHttpRequest.5.1, Msxml2.XMLHTTP ...
CreateFormData(ByRef retData, ByRef retHeader, objParam) {
New CreateFormData(retData, retHeader, objParam)
}
; Used for WinInet
CreateFormData_WinInet(ByRef retData, ByRef retHeader, objParam) {
New CreateFormData(safeArr, retHeader, objParam)
size := safeArr.MaxIndex() + 1
VarSetCapacity(retData, size, 1)
DllCall("oleaut32\SafeArrayAccessData", "ptr", ComObjValue(safeArr), "ptr*", pdata)
DllCall("RtlMoveMemory", "ptr", &retData, "ptr", pdata, "ptr", size)
DllCall("oleaut32\SafeArrayUnaccessData", "ptr", ComObjValue(safeArr))
}
Class CreateFormData {
__New(ByRef retData, ByRef retHeader, objParam) {
CRLF := "`r`n"
Boundary := this.RandomBoundary()
BoundaryLine := "------------------------------" . Boundary
; Loop input paramters
binArrs := []
For k, v in objParam
{
If IsObject(v) {
For i, FileName in v
{
str := BoundaryLine . CRLF
. "Content-Disposition: form-data; name=`"" . k . "`"; filename=`"" . FileName . "`"" . CRLF
. "Content-Type: " . this.MimeType(FileName) . CRLF . CRLF
binArrs.Push( BinArr_FromString(str) )
binArrs.Push( BinArr_FromFile(FileName) )
binArrs.Push( BinArr_FromString(CRLF) )
}
} Else {
str := BoundaryLine . CRLF
. "Content-Disposition: form-data; name=`"" . k "`"" . CRLF . CRLF
. v . CRLF
binArrs.Push( BinArr_FromString(str) )
}
}
str := BoundaryLine . "--" . CRLF
binArrs.Push( BinArr_FromString(str) )
retData := BinArr_Join(binArrs*)
retHeader := "multipart/form-data; boundary=----------------------------" . Boundary
}
RandomBoundary() {
str := "0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z"
Sort, str, D| Random
str := StrReplace(str, "|")
Return SubStr(str, 1, 12)
}
MimeType(FileName) {
n := FileOpen(FileName, "r").ReadUInt()
Return (n = 0x474E5089) ? "image/png"
: (n = 0x38464947) ? "image/gif"
: (n&0xFFFF = 0x4D42 ) ? "image/bmp"
: (n&0xFFFF = 0xD8FF ) ? "image/jpeg"
: (n&0xFFFF = 0x4949 ) ? "image/tiff"
: (n&0xFFFF = 0x4D4D ) ? "image/tiff"
: "application/octet-stream"
}
}
BinArr.ahk (unchanged)
Code: Select all
; Update: 2015-6-4 - Added BinArr_ToFile()
BinArr_FromString(str) {
oADO := ComObjCreate("ADODB.Stream")
oADO.Type := 2 ; adTypeText
oADO.Mode := 3 ; adModeReadWrite
oADO.Open()
oADO.Charset := "UTF-8"
oADO.WriteText(str)
oADO.Position := 0
oADO.Type := 1 ; adTypeBinary
oADO.Position := 3 ; Skip UTF-8 BOM
return oADO.Read, oADO.Close
}
BinArr_FromFile(FileName) {
oADO := ComObjCreate("ADODB.Stream")
oADO.Type := 1 ; adTypeBinary
oADO.Open
oADO.LoadFromFile(FileName)
return oADO.Read, oADO.Close
}
BinArr_Join(Arrays*) {
oADO := ComObjCreate("ADODB.Stream")
oADO.Type := 1 ; adTypeBinary
oADO.Mode := 3 ; adModeReadWrite
oADO.Open
For i, arr in Arrays
oADO.Write(arr)
oADO.Position := 0
return oADO.Read, oADO.Close
}
BinArr_ToString(BinArr, Encoding := "UTF-8") {
oADO := ComObjCreate("ADODB.Stream")
oADO.Type := 1 ; adTypeBinary
oADO.Mode := 3 ; adModeReadWrite
oADO.Open
oADO.Write(BinArr)
oADO.Position := 0
oADO.Type := 2 ; adTypeText
oADO.Charset := Encoding
return oADO.ReadText, oADO.Close
}
BinArr_ToFile(BinArr, FileName) {
oADO := ComObjCreate("ADODB.Stream")
oADO.Type := 1 ; adTypeBinary
oADO.Open
oADO.Write(BinArr)
oADO.SaveToFile(FileName, 2)
oADO.Close
}
(Working on a general PushBullet class for AHKv2 but the file sending here is the last wrench holding me up from supporting the core elements of the PushBullet API)