1)Code Tested on Win7 32bit having IE8 and chrome debugging mode worked
2)Code Tested on Win10 64bit chrome debugging mode worked
Download DLL:
We only need WebSocketAsio-x86.dll or WebSocketAsio-x64.dll in Script Dir
https://github.com/pdckxd/WebSocketAsioAHK/tree/master/bin
Class:
Code: Select all
/*
WS2 WebSocket 2 (No IE support) Class by XEO786
project started with
Based on https://github.com/agrippa1994/WebSocket-API and https://github.com/xNilsx/Websocket-API
but there was no websocket 64bit dll
now we using dllfiles from pdckxd WebSocketAsioAHK
following Class will need websocket dll files in script Dir
https://github.com/pdckxd/WebSocketAsioAHK/tree/master/bin
now using WebSocketAsioAHK for 32bit + 64bit support
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;; Intelegent Class ;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
This Class remebers how many __new() WS2 have been created
one can check how many working websocket have been created using WS2.base.WScount
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;Dll Loading and Unloading ;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Dll unloaded and loaded automatically no matter how many New WS2 Created
1) load DLL automatically when Very First WS2 called/created i.e. obj := New WS2
2) unload DLL automatically when Last existing WS get deleted i.e. WS2 := ""
but one can unload Dll and Load DLL manually as per following Condition
1) You cannot Unload Dll when there are more than one working Websocket i.e. WS2.base.WScount > 1
2) Dll can only be unloaded manually when there is Last Websocket i.e. WS2.base.WScount = 1, WS2.UnloadDll() return 0 when failed
3) One can only load Dll manually after manually unloading i.e. WS2.LoadDll() return 0 when failed
examples
ws1 := New WS2 ; create new Websocket and Load Dll library
ws2 := New WS2 ; create another Websocket but will not Load Dll library again
;this will first check for connection if connection found it will first disconnect then delete ws2
ws2 := ""
; after dealing with connection it will unload dll using dllcall FreeLibrary then delete ws1
ws1 := ""
*/
Class WS2
{
__new()
{
static WScount := 0
if(this.base.dll != 1) ; if library is already loaded
this.LoadDll()
this.base.WScount := ++WScount
}
__delete()
{
if this.isconnected()
if this.Disconnect()
while( this.Connection = 1) ; Wiating for connection termination
sleep, 10
this.base.WScount := this.base.WScount - 1
if( this.base.WScount = 0) ; unload dll when Last WS getting deleted/closed
if this.base.dll
this.unLoadDll()
}
UnloadDll()
{
if( this.base.WScount > 1) ; incase someone manually unload dll
return
if this.isconnected() ; checking WS connection before unloading
if this.Disconnect()
while( this.Connection = 1) ; confirming ws connection terminated
sleep, 10
DllCall("FreeLibrary", "Ptr", this.base.hModule)
this.base.dll := ""
this.base.dllname := ""
return 1
}
LoadDll()
{
if(this.base.dll = 1) ; if library is already loaded
return
this.base.dll := 1
if(A_PtrSize = 4)
int := "int", Dll := "x86"
else
int := "int64", Dll := "x64"
this.base.dllname := "WebSocketAsio-" Dll ".dll"
hModule := DllCall("LoadLibrary", "str", A_ScriptDir "\WebSocketAsio-" Dll ".dll")
if(hModule == -1 || hModule == 0)
{
MsgBox, 48, Error, The dll-file couldn't be found!
ExitApp
}
this.base.hModule := hModule
DllCall(this.base.dllname "\websocket_register_on_connect_cb" , int, RegisterCallback(this._Handshake,"F",,&this), "char")
DllCall(this.base.dllname "\websocket_register_on_fail_cb" , int, RegisterCallback(this._Fail,"F",,&this), "char")
DllCall(this.base.dllname "\websocket_register_on_disconnect_cb" , int, RegisterCallback(this._close,"C F",,&this), "char")
DllCall(this.base.dllname "\websocket_register_on_data_cb" , int, RegisterCallback(this._receive,"C F",,&this), "char")
return 1
}
Connect(hostStr)
{
if(this.base.dll = 0)
return ;DLL have been manually unloaded Previously `nConnection Fail...!
this.uri := hostStr
return DllCall(this.base.dllname "\websocket_connect", "Str", hostStr, "Char")
}
Disconnect()
{
return DllCall(this.base.dllname "\websocket_disconnect", "UChar")
}
Send(data, len, is_binary)
{
This.response := "" ; simply empty respose before sending new request so we can simply wait
return DllCall(this.base.dllname "\websocket_send", "Str", data, "Ptr", len, "UChar", is_binary, "UChar")
}
isconnected()
{
return DllCall(this.base.dllname "\websocket_isconnected", "UChar")
}
_Handshake()
{
Critical
this := Object(A_EventInfo)
this.Connection := 1
}
_fail()
{
Critical
this := Object(A_EventInfo)
this.Connection := 2
}
_close()
{
Critical
this := Object(A_EventInfo)
if this.notify
MsgBox, 48, WS Notify, Disconnect...!
this.Connection := 3
}
_receive(length,a,b,c,D,e,f,g,h,data)
{
Critical
this := Object(A_EventInfo)
this.response := StrGet(Data,length,"UTF-8")
}
}
Code: Select all
#NoEnv
#SingleInstance Force
#Include WebSocket.ahk
ws := new WS2()
; I used chrome debugging mode method
; 1) run chrome into debugging protocole mode using localhost and port for example 127.0.0.1:9222
; 2) open some website in new tab
; 3) navigate to some Web page like . www.google.com
; open some other browser
; 4) navigate to 127.0.0.1:9222/json
; 5) there you get that id
pageid := "AB5D8071E53C71B3706DEB230C68EC1F"
wsUri := "ws://127.0.0.1:9222/devtools/page/" pageid
Gui, Add, ListBox, x12 y10 w590 h400 vView ,
; Edits
Gui, Add, Edit, x372 y420 w120 h20 vHost, % wsUri
Gui, Add, Edit, x22 y420 w260 h20 vMessage, {"id":1,"method":"DOM.getDocument"}
; Buttons
Gui, Add, Button, x502 y410 w100 h20 gBtnConnect, Connect
Gui, Add, Button, x502 y430 w100 h20 gBtnDisconnect, Disconnect
Gui, Add, Button, x292 y420 w70 h20 gBtnSend, Send
; Show GUI
Gui, Show, w620 h471, Websocket2
return
websocket_register_on_connect_cb()
{
msgbox, here
}
GuiClose:
ws := "" ; being last WS2 this disconnect and unload Dll
Gui, Destroy
exitapp
BtnConnect:
GuiControlGet, ip,, Host
if(strLen(ip) == 0)
{
addText("The IP textfield doesn't contain any string!")
return
}
res := ws.connect(ip)
if(res == 0)
{
addText("ws.connect() returned 0.")
return
}
while !(ws.connection = 1)
{
sleep, 10
}
if(ws.connection = 1)
addText("The connection has been established!")
else if(ws.connection = 2)
addText("The connection couldn't be created!")
return
BtnDisconnect:
if(!ws.disconnect())
{
addText("The connection couldn't be closed. The connection is already closed!")
return
}
addText("The connection has been closed!")
return
BtnSend:
if(ws.connection = 2)
{
addText("Unable to Send connection with Websocket have aleready been terminated")
return
}
if(!ws.isconnected())
{
addText("The connection isn't estabilshed!")
return
}
GuiControlGet, msg,, Message
if(strLen(msg) == 0)
{
addText("The message textfield doesn't contain any string!")
return
}
if(ws.send(msg, strLen(msg), false))
addText("The message has been sent!")
else
{
addText("The message couldn't be sent!")
return
}
while !ws.response
{
sleep, 10
}
addText("Data has been received:" ws.response)
return
addText(t)
{
GuiControl,, View, %t%
}
Thanks:
agrippa1994 for his Websocket
pdckxd for his WebSocketAsioAHK
Geek aka Geekdude, Oldman, helgef their code and posts helped to understand callbacks binding with class methods
swagfag for helping me correct stuff
Changes:
1) Shortened few function Names for writing convenience
2)have implemented response mechanism to Websocket class by binding register callback to class methods
3)Made few changes in class point out by swagfag
4)I left Agrippa Websocket.dll reason I didnot find 64bit support
5)now using WebSocketAsioAHK dll by pdckxd reason now WS2 support 32bit and 64 and I have change the class entirely
6)swagfag pointed out dll library loading so I made this class to be intelligent enough it decide by itself when to load and unload dll