latest AHK_H not working as expected

Ask for help, how to use AHK_H, etc.
User avatar
dd900
Posts: 121
Joined: 27 Oct 2013, 16:03

latest AHK_H not working as expected

03 Mar 2015, 21:32

in AHK_H (1.1.13.0) this works

Code: Select all

thread1 := AhkDllThread( A_ScriptDir "\autohotkey.dll" )
thread1.ahktextdll("msgbox 1")
sleep 5000
exitapp
but in the latest AHK_H (1.1.19.3) it does not work.

Edit:
To be more specific the following works fine with 1.1.13.0

Code: Select all

#SingleInstance Force
DetectHiddenWindows On
FileEncoding utf-8
SetWorkingDir %A_ScriptDir%
OnExit Exit

MobyURL := "http://www.mobygames.com"
MobyStatsURL := MobyURL "/moby_stats"
MobySearchURL := MobyURL "/search/quick?q="
MobyNewGamesURL := MobyURL "/stats/recent_entries"
MobySitemapURL := MobyURL "/images/sitemap/sitemap_index.xml"
dataDir := A_WorkingDir "\Data"
resDir := A_WorkingDir "\Res"
smFile := dataDir "\sitemap.gS"
loadGIF := resDir "\loading.gif"

Systems := Object()
searchInts := Object()
Sitemaps := Object()

GlobalVarsScript( "Systems", 0, Systems )
GlobalVarsScript( "searchInts", 0, searchInts )
GlobalVarsScript( "Sitemaps", 0, Sitemaps )
GlobalVarsScript( "Systems_List", 100 )

mainGuiHwnd := New_Gui( "center", "w600 h400", "+LabelmainGuiThread_", "Undecided - ?????????" )
gosub mainGui_Build
loadImg := HTMLImage( mainGuiHwnd, loadGIF, 600 - 160, 400 - 160, 150, 150 )
ShowGui( mainGuiHwnd )

dllFunctions := CreateScript( ""
	. "GetSystems{}`n"
	. "GetSearchIntegers{}`r`n"
	. "GetSitemapNames_F{}`n"
	. "GetSitemapNames_W{}`n"
	. "CheckSitemapNames{}`n"
	. "CreateSitemapFile{}`n"
	. "htmlLoad{}`n"
	. "CheckJQuery{}`n"
	. "UrlToVar{}`n"
	. "sReplace{}`n"
	. "msg{}`n"
	. "StrX{}" )

Loop 5
	dllThread%A_Index% := AhkDllThread( A_WorkingDir "\gScrape.dll" )

dllThread1.ahktextdll( GlobalVarsScript() "GetSearchIntegers( searchInts, """ MobySearchURL """ )`n" dllFunctions )
dllThread2.ahktextdll( GlobalVarsScript()
	. "GetSystems( Systems, """ MobyStatsURL """ )`n"
	. "for k, v in Systems`n{`n"
	. "if k in SystemCount`n"
	. "continue`n"
	. "Systems_List .= k ""``n""`n}`n"
	. "StringTrimRight Systems_List, Systems_List, 1`n"
	. dllFunctions )
dllThread3.ahktextdll( GlobalVarsScript()
	. "while !Systems.SystemCount`n"
	. "sleep 500`n"
	. "if !FileExist( """ smFile """ ) {`n"
	. "GetSitemapNames_W( Sitemaps, """ MobySitemapURL """ )`n"
	. "CreateSitemapFile( Sitemaps, """ smFile """ )`n} else {`n"
	. "GetSitemapNames_F( Sitemaps, """ smFile """ )`n"
	. "if CheckSitemapNames( Sitemaps, Systems ) {`n"
	. "GetSitemapNames_W( Sitemaps, """ MobySitemapURL """ )`n"
	. "CreateSitemapFile( Sitemaps, """ smFile """ )`n}`n}`n"
	. dllFunctions )

while !Systems.SystemCount || !searchInts.HasKey( "zzzzzz" ) || !Sitemaps.HasKey( "zzzzzz" )
	sleep 500

Loop 3
	dllThread%A_Index%.ahkterminate()
loadImg.src := ""
EmptyMem()
msg( Sitemaps.nes "`n" Systems.NES.gameCount "`n" searchInts.NES )
return




Exit:
{
	CloseGui( mainGuiHwnd )
	Loop 5
		dllThread%A_Index%.ahkterminate()
	exitapp
}

mainGui_Build:
{
	Gui %mainGuiHwnd%:margin, 0, 0
	return
}

Escape::
mainGuiThread_Close:
{
	exitapp
}




sReplace( var, SearchText, ReplaceText:="", All:="" ) {
	StringReplace out, var, %SearchText%, %ReplaceText%, % All ? "All" : ""
	return out
}

msg( lpText:="", lpCaption:="", uType:=0x00000000, hwnd:="" ) {
	return DllCall( "MessageBox", UInt, hwnd, Str, lpText, Str, lpCaption, UInt, uType )
}

New_Gui( Pos:="", Size:="", Options:="", WinTitle:="", Color:="", pWin:="" ) {
    if pWin
        Gui New, % "-DPIScale +LastFound " Options " +Parent" pWin, %WinTitle%
    else
        Gui New, -DPIScale +LastFound %Options%, %WinTitle%
    hwnd := WinExist()
    if pWin
        DllCall( "SetParent", UInt, hwnd, UInt, pWin )
    Gui %hwnd%:Color, % Color = "" ? GetSysColor( 15 ) : Color
    Gui %hwnd%:Show, %Pos% %Size% Hide
    return hwnd
}

ShowGui( hwnd, Pos:="", Size:="", ShowOptions:="", GuiOptions:="" ) {
    if GuiOptions
        Gui %hwnd%:%GuiOptions%
    Gui %hwnd%:Show, %Pos% %Size% %ShowOptions%
    return
}

CloseGui( hwnd ) {
    Gui %hwnd%:Destroy
    return
}

HTMLImage( guiHwnd, Image, X, Y, W, H, BackgroundColor="", Id="AnimatedGif", eventHandler="" ) {
    DefaultGUIColor := DllCall( "GetSysColor", UInt, 15 )
    R := DefaultGUIColor & 0xFF
    G := ( DefaultGUIColor >> 8 ) & 0xFF
    B := ( DefaultGUIColor >> 16 ) & 0xFF
    DefaultGUIColor := "rgb(" R ", " G ", " B ")"
    Gui %guiHwnd%:Add, ActiveX, x%X% y%Y% w%W% h%H% +HwndGifHwnd, MSHTML:
    GuiControlGet HtmlObj, %guiHwnd%:, %GifHwnd%
    HtmlObj.Body.style.BackgroundColor := BackgroundColor = "" ? DefaultGUIColor : BackgroundColor
    HtmlObj.Body.style.margin := 0
    HtmlObj.Body.style.padding := 0
    out := HtmlObj.createElement( "img" )
    out.id := Id
    out.src := Image
    out.style.position := "absolute"
    out.style.left := 0
    out.style.top := 0
    out.style.width := "100%"
    out.style.height := "100%"
    out.style.minWidth := "100%"
    out.style.minHeight := "100%"
    out.style.visibility := "visible"
    HtmlObj.Body.appendChild( out )
    if eventHandler
        ComObjConnect( out, eventHandler )
    return out
}

GetSysColor( DisplayElement:=1 ) {
    VarSetCapacity( HexClr,7,0 )
    SClr := DllCall( "GetSysColor", UInt, DisplayElement )
    RGB := ( ( ( SClr & 0xFF ) << 16 ) | ( SClr & 0xFF00 ) | ( ( SClr & 0xFF0000 ) >> 16 ) )
    DllCall( "msvcrt\sprintf", Str, HexClr, Str, "%06X", UInt, RGB )
    Return HexClr
}

GetSystems( Systems, statsUrl ) {
	statDoc := htmlLoad( statsUrl )
	pWin := statDoc.parentWindow
	jArray := pWin.JQuery( "tr:contains('Platform Stats')" ).nextAll().children( "td.sbL " ).toArray()
	jArray2 := pWin.JQuery( "tr:contains('Platform Stats')" ).nextAll().children().children( "a" ).toArray()
	Loop % jArray.length {
		sysName := jArray[ A_Index - 1 ].innertext, 10, 10, 1
		sysURL := jArray2[ A_Index - 1 ].href, 40, 40, 2
		StringSplit linkName, sysURL, /
		Systems.Insert( sysName, {} )
		Systems[ sysName ].Insert( "gameCount", sReplace( jArray2[ A_Index - 1 ].innertext, "," ) )
		Systems[ sysName ].Insert( "systemURL", sReplace( sysURL, "about:" ) )
		Systems[ sysName ].Insert( "linkName", linkName4 )
	}
	Systems.Insert( "SystemCount", pWin.JQuery( "td.sbL:contains('Total Platforms')" ).next( ":first" ).text() )
}

GetSearchIntegers( Integers, searchURL ) {
	searchDoc := htmlLoad( searchURL )
	pWin := searchDoc.parentWindow
	jArray := pWin.JQuery( "#platformInput" ).children().toArray()
	Loop % jArray.length
		Integers.Insert( jArray[ A_Index - 1 ].innertext, jArray[ A_Index - 1 ].value )
	Integers.Insert( "zzzzzz", "zzzzzz" )
}

GetSitemapNames_F( Sitemaps, sitemapFile ) {
	FileRead smNamesVar, %sitemapFile%
	Loop Parse, smNamesVar, `n
	{
		Loop Parse, A_LoopField, CSV
		{
			if A_Index = 1
				key := A_LoopField
			else
				Sitemaps.Insert( key, A_LoopField )
		}
	}
}

GetSitemapNames_W( Sitemaps, sitemapURL ) {
	MobySitemap := UrlToVar( sitemapURL )
	while smURL := StrX( MobySitemap, "<sitemap>", N, 9, "</sitemap>", 1, 10, N )
	{
		sys_smURL := StrX( smURL, "<loc>", 1, 5, "</loc>", 1, 6 )
		if InStr( sys_smURL, "gamegroups.xml" )
			continue
		sys_smURLVar := UrlToVar( sys_smURL )
		firstGameURL := StrX( sys_smURLVar, "<loc>", 1, 5, "</loc>", 1, 6 )
		StringSplit smName, sys_smURL, _
		StringSplit sLinkName, firstGameURL, /
		if ( checkName != sLinkName5 )
			Sitemaps.Insert( sLinkName5, smName2 )
		checkName := sLinkName5
	}
	Sitemaps.Insert( "zzzzzz", "zzzzzz" )
}

CheckSitemapNames( Sitemaps, SystemsObj ) {
	updtNeeded := 0
	for k in SystemsObj
	{
		if k in SystemCount
			continue
		if !Sitemaps[ SystemsObj[ k ].linkName ] && SystemsObj[ k ].gameCount {
			updtNeeded := 1
			break
		}
	}
	if !updtNeeded
		Sitemaps.Insert( "zzzzzz", "zzzzzz" )
	return updtNeeded
}

CreateSitemapFile( Sitemaps, sitemapFile ) {
	if FileExist( sitemapFile )
		FileDelete %sitemapFile%
	for k, v in Sitemaps
	{
		if k in zzzzzz
			continue
		out .= """" k """,""" v """`n"
	}
	StringTrimRight out, out, 1
	FileAppend %out%, %sitemapFile%
}

htmlLoad( url ) {
	doc := ComObjCreate( "HtmlFile" )
	docText := UrlToVar( url )
	doc.open()
    doc.write( docText )
	doc.close()
	Loop
	{
		sleep 500
		if doc.readyState in complete
			break
	}
	CheckJQuery( doc )
	return doc
}

CheckJQuery( doc ) {
	if !IsObject( doc.parentWindow.Jquery ) {
		jQueryVar := UrlToVar( "https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js" )
		doc.parentWindow.execScript( jQueryVar )
		Loop
		{
			sleep 500
			if IsObject( doc.parentWindow.Jquery )
				break
		}
	}
	return
}

UrlToVar( URL, Charset:="utf-8", URLCodePage:="65001", Timeout:=5 ) {
	ComObjError( 0 )
	WebRequest := ComObjCreate( "WinHttp.WinHttpRequest.5.1" )
	WebRequest.Option( 2 ) := URLCodePage
	Loop
	{
		if A_Index = 3
		{
			msg( "There was a problem downloading the requested url:`n`n" URL "`n`nPlease close the application and try again.", "ERROR" )
			exitapp
		}
		WebRequest.Open( "GET", URL, true )
		WebRequest.Send()
		WebRequest.WaitForResponse( Timeout )
		if ( WebRequest.Status = 200 )
			break
		else
			continue
	}
	ADO := ComObjCreate( "adodb.stream" )
	ADO.Type := 1
	ADO.Mode := 3
	ADO.Open()
	ADO.Write( WebRequest.ResponseBody )
	ADO.Position := 0
	ADO.Type := 2
	ADO.Charset := Charset
	return ADO.ReadText()
}

StrX(H, BS="", BO=0, BT=1, ES="", EO=0, ET=1, ByRef N="") {
Return SubStr(H,P:=(((Z:=StrLen(ES))+(X:=StrLen(H))+StrLen(BS)-Z-X)?((T:=InStr(H,BS,0,((BO<0)?(1):(BO))))?(T+BT):(X+1)):(1)),(N:=P+((Z)?((T:=InStr(H,ES,0,((EO)?(P+1):(0))))?(T-P+Z+(0-ET)):(X+P)):(X)))-P)
}
Using the latest AHK_H from git none of the dll threads start. I also used the latest libs that were in the git package. There seems to be an error with CreateScript(). The older version I have works fine , but the latest keeps telling me Function GetSearchIntegers() cannot contain functions.
HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: latest AHK_H not working as expected

04 Mar 2015, 04:37

There was an error in DynaCall that has been fixed now.
Also CreateScript has been fixed.
User avatar
dd900
Posts: 121
Joined: 27 Oct 2013, 16:03

Re: latest AHK_H not working as expected

04 Mar 2015, 05:22

thanks. I will give it another go after work.
RHCP
Posts: 202
Joined: 30 Sep 2013, 10:59

Re: latest AHK_H not working as expected

04 Mar 2015, 06:49

I've been using AHK_H MD 32W v1.1.15.00 for a while without issue, but im running into trouble using the latest version.

Is this the correct link? https://github.com/HotKeyIt/ahkdll-v1-release
What happened to the MD/non-MD versions?

I've deleted my old lib folder and replaced it with the one from the current release.

When calling the function the passed values are ignored. It works fine in 1.1.15.
If i make the function variables 'a' and 'b' required i.e. f(a,b)... then it complains that that not enough parameters were passed to the function.

Code: Select all

#SingleInstance, Force
#NoEnv

thread := AhkDllThread("Included Files\ahkH\AutoHotkey.dll")

 ;threadText = #persistent`nmsgbox`nf(a, b)`n{`nmsgbox `%a`% `%b`%`n}
thread.ahktextdll(generateScript())

f1::
thread.ahkPostFunction("f", "ignored1", "ignored2")
; results in the message box displaying  " 1 2 "
; I.e. the default values for variables a and b are used
return 
f2::
thread.ahkFunction("f", "ignored1", "ignored2")
; results in the message box displaying  " 1 2 "
; I.e. the default values for variables a and b are used
return 

generateScript()
{
    script = 
    (   %
        #Persistent
    	f(a := "1", b := "2")
        {
        	msgbox %a% %b%
        	return
        }
    )
    return script
}
Thanks.
HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: latest AHK_H not working as expected

04 Mar 2015, 07:28

What happened to the MD/non-MD versions?
There is no AutoHotkey.exe and AutoHotkeySC.bin MD version anymore and no AutoHotkey[Mini].dll non-MD version.

AutoHotkey.exe and SC.bin include AutoHotkey.dll and AutoHotkeyMini.dll as well as msvcr100.dll.
Using MemoryLoadLibrary, msvcr100.dll is not required anmore.
If you are using AHK_H version of AutoHotkey.exe and AutoHotkeySC.bin, there is a new function included.
With included dlls and this function you do not need AutoHotkey.dll anymore.

thread:=AhkThread(script:="",param:="",IsFile:=0,dll:="AutoHotkey.dll")
thread:=AhkMini(script:="",param:="",IsFile:=0,dll:="AutoHotkeyMini.dll")
- thread: Object that can run ahkdll functions like thread.ahkdll("File.ahk")
- script: script to start in new thread. "" will start "#Persistent`n#NoTrayIcon". 0 will return ahkdll object but not start a thread, use ahkdll or ahktextdll to start new thread
- param: parameters to pass to script.
- IsFile: true = script parameter is a file on disk. false = script parameter is a script as text
- dll: dll to be used for the thread
Note: Thread started by AhkThread() will not be freed until program exits.

For example:

Code: Select all

obj := CriticalObject() ; Create new critical object
Loop, 3 ; Create 3 Threads. 
	AhkThread%A_Index% := AhkThread("obj:=CriticalObject(" (&obj) ")`nLoop`nobj[" A_Index "]:= A_Index")
Loop ; Show current content of object. 
	ToolTip, % obj.1 "`n" obj.2 "`n" obj.3
Esc::ExitApp
EDIT:
Updated MiniThread should be AhkMini
RHCP
Posts: 202
Joined: 30 Sep 2013, 10:59

Re: latest AHK_H not working as expected

04 Mar 2015, 10:00

Thanks for the quick fix! These are some great changes!

Unfortunately im still having issues. One of the worker threads is throwing up this error: http://imgur.com/ZtlL6eV

The issue is tied up with sharing an object between the AHK.exe and ahkdll worker thread. This script is massive, but commenting out these lines in the worker thread 'fixes' it. When I have some more free time I will play around with it some more (create a better test case) - as well as replace AhkDllThread() with AhkThread/AHKmini()

Code: Select all

; main script launched (autohotkey.exe)
Global aThreads := CriticalObject() ; Thread safe object
global data := []
global CriSec := CriticalSection()

aThreads.worker1 := AhkDllThread("Included Files\ahkH\AutoHotkey.dll")
aThreads.worker1.ahktextdll(GlobalVarsScript("aThreads", 0, aThreads) scriptString,, CriSec " " &data)
return 




;;;;;;
; scriptString (worker thread) has something like this in it
; which is now causing issues.
;;;;

; auto-exec
CriSec = %1% 
data = %2% 
data := Object(data+0)
return 


; timed event
thread, NoTimers, true
Lock(CriSec)
data.remove(data.MinIndex(), data.MaxIndex())

for type, string in obj
	data[type] := string
UnLock(CriSec)
thread, NoTimers, false
Last edited by RHCP on 06 Mar 2015, 01:51, edited 1 time in total.
HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: latest AHK_H not working as expected

04 Mar 2015, 12:40

That is the down side of having one version of exe/dll only, you can't share data between exe and dll anymore.
But you can simply start your main script in dll or declare the shared objects in separate dll.
guest3456
Posts: 3463
Joined: 09 Oct 2013, 10:31

Re: latest AHK_H not working as expected

04 Mar 2015, 13:19

when were these AHK_H changes introduced? is there a changelog somewhere?

HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: latest AHK_H not working as expected

04 Mar 2015, 13:41

Today, changes are only on github.
I found a bug with 64-bit, just in case the previous versions can be found here.
User avatar
dd900
Posts: 121
Joined: 27 Oct 2013, 16:03

Re: latest AHK_H not working as expected

04 Mar 2015, 23:47

thanks for the updates. Using the same script as above AhkThread() works great, but there is some slight lag in my gif animation when the threads start. Using AhkDllThread() there is no lag, but when i close the gui (exitapp) i get a memory error.

screenshots of error:
http://1drv.ms/1KoqogB
http://1drv.ms/1Koqzsn
http://1drv.ms/1w5yKDe
RHCP
Posts: 202
Joined: 30 Sep 2013, 10:59

Re: latest AHK_H not working as expected

05 Mar 2015, 23:45

HotKeyIt wrote:That is the down side of having one version of exe/dll only, you can't share data between exe and dll anymore.
But you can simply start your main script in dll or declare the shared objects in separate dll.
I was wondering if that had anything to do with it. Could I just compile the autoHotkey.exe from source using the MD (Multi-threaded DLL) flag setting? There are couple of minor (40 lines or so) additions that I need to add to the AHK source for my script to run correctly (hence why I rarely update), and I remember last time I couldn't compile the dlls as that required VS 2010 professional.

Thanks.
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: latest AHK_H not working as expected

06 Mar 2015, 01:25

[...] I remember last time I couldn't compile the dlls as that required VS 2010 professional.
I see no reason you shouldn't be able to use Visual C++ Express 2010, 2012 or 2013 (I've used all three to compile dlls), or Visual Studio 2013 Community Edition, which "includes all the great functionality of Visual Studio Professional 2013".
RHCP
Posts: 202
Joined: 30 Sep 2013, 10:59

Re: latest AHK_H not working as expected

06 Mar 2015, 01:49

This was the error generated when compiling DLLs
source\dllmain.cpp(31): fatal error C1083: Cannot open include file: 'atlbase.h': No such file or directory
Hotkeyit suggested it was due to express and other posts seemed to back that up. I only needed to modify the exe build, so I never bothered to try any of the 'fixes'. After encountering other issues with VS i'm a little reluctant to mess around with it when it's working. I might try installing the community edition though. Thanks.
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: latest AHK_H not working as expected

06 Mar 2015, 02:54

I see; HotKeyIt must be using ATL in his projects. There is nothing about the Express edition that should stop it compiling dlls in general, or base AutoHotkey 1.1.
HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: latest AHK_H not working as expected

13 Mar 2015, 16:06

I think all errors should be fixed now.

MSVCR is not included anymore and all files are compiled with /MD flag so require msvcr100.dll.

I had also problems compiling dll in Visual C++ Express and found no way around.
As Lexikos sugested Visual Studio 2013 Community Edition should be the right choice.

Return to “Ask for Help”

Who is online

Users browsing this forum: No registered users and 15 guests