Unable To Run Ahk2Exe to Compile Custom Code
Opened this issue · 27 comments
Issue: Unable to run Ahk2Exe to allow compilation of AHK_H V2 Scripts due to AHK V2 updating VarSetCapacity() to VarSetStrCapacity().
Steps to Reproduce:
- Extract Compiler folder from this Repository into C:\Program Files\AutoHotkey\Compiler
- Extract files from x64w folder from this Repository into C:\Program Files\AutoHotkey\Compiler
- Rename AutoHotkey.exe to Ahk2Exe.exe (deleting/backing up old)
- Run Ahk2Exe.exe
- Errors appear, e.g. https://i.imgur.com/jIXvsG9.png https://i.imgur.com/7y1Mds7.png
Cause: AHK V2 Updated VarSetCapacity() to VarSetStrCapacity()
Old: https://www.autohotkey.com/docs/commands/VarSetCapacity.htm
New: https://lexikos.github.io/v2/docs/commands/VarSetStrCapacity.htm
Version: Latest AHK_H V2
After manually resolving the VarSetCapacity() errors without properly dealing with the fillValue being removed (due to a lack of core understanding), I have now come across this error. https://i.imgur.com/0ChQA5h.png
I have resolved this for my personal use by manually adding the required keys.
Next bottleneck appears to be a GuiCreate error which I am currently unfamiliar with how to resolve. https://i.imgur.com/dQpg4AP.png
Further research shows that this issue has been confirmed on the AutoHotkey Forums by another user. This issue was last resolved by HotKeyIt in May, but has since returned.
Source: https://www.autohotkey.com/boards/viewtopic.php?p=338701#p338701
For better representation as to when the issue was merged into the code, I went back and downloaded the repo as of commit 9592392 and tested the Ahk2Exe, it opens without throwing any errors.
Due to v2.110 VarSetCapacity errors, I attempted a v2.109 custom compiled bin BinRun() alongside the v2.109 Ahk2Exe. This did not work as expected either with the resulting message: ERROR: e_magic not found
.
For now I'll go ahead and merge my 11 files into 1 massive bloated file, but I'd like to resolve this moving forward, I'm just not sure how at this time after posting a forum thread and asking a few people in the Discord server.
010: file := FileRead("testTwo.exe","RAW")
011: PID := BinRun(&file)
---- BinRun.ahk
004: if !MEM_COMMIT
005: IMAGE_DOS_HEADER :="WORD e_magic;WORD e_cblp;WORD e_cp;WORD e_crlc;WORD e_cparhdr;WORD e_minalloc;WORD e_maxalloc;WORD e_ss;WORD e_sp;WORD e_csum;WORD e_ip;WORD e_cs;WORD e_lfarlc;WORD e_ovno;
024: if (Type(pData)!="Integer")
037: if InStr(cmdLine,"
")
044: IDH := Struct(IMAGE_DOS_HEADER,pData)
045: if (IDH.e_magic != IMAGE_DOS_SIGNATURE)
046: MsgBox("ERROR: e_magic not found") (145.36)
@HotKeyIt I apologize for the ping, I am sure you are busy external to this project. I would love to know if you plan on resolving this issue.
Thanks for your time,
Deafwave
Many thanks for your report and findings, I will surely resolve the issue.
I think I will find some time to look into it this or next week after I merge latest v2 ;)
Sounds great, thanks HotKeyIt. I'm extremely glad that you're still alive! Looking forward to the updates. :)
@HotKeyIt Is there some place where I can donate to you for spending your time creating this?
This should be working fine now, I have updated v1 Compiler to support all #Directives and v2 compiling.
Thanks for this! Unfortunately, I'm running into a couple other issues updating to the latest compiled version in this repo.
These were all tested pre-compile using the AutoHotkey.exe
, AutoHotkey.dll
, and vcruntime140.dll
in x64w
of this repo.
Hotkey("F1", "createMessageBox") ; <--- Error: Invalid callback function
; Hotkey("F1", createMessageBox) ; <--- Warning: This variable appears to never be assigned a value. Specifically: global createMessageBox -> Error: Nonexistent hotkey. Specifically: F1
; Hotkey("F1", createMessageBox()) ; <--- Immediately invokes MsgBox with asdasd. Upon pressing OK it throws: Error: Nonexistent hotkey. Specifically: F1
Return
createMessageBox() {
global
MsgBox("asdasd")
Return
}
defaultObject := {
testVar: "yay, it worked"
}
CritObj := CriticalObject(defaultObject)
additionalThread := "
(
CritObj := CriticalObject(A_Args[1])
CritObj.testVar := "Manipulated CritObj String"
MsgBox(CritObj.testVar)
)"
; exampleThread := AHKThread(additionalThread, &CritObj "", "testSecondThread", false) ; <-- Error: Syntax error Specifically &CritObj ""
exampleThread := AHKThread(additionalThread, &CritObj, "testSecondThread", false) ; <-- Error: Syntax error Specifically &CritObj
; exampleThread := AHKThread(additionalThread, CritObj, "testSecondThread", false) ; <-- Error in #include file This value of type "Object" has no property named "Ptr".
; exampleThread := AHKThread(additionalThread, CritObj "", "testSecondThread", false) ; <-- Error: Expected a String but got an Object.
Sleep(10000) ; Janky Test
Return
Thanks for your time,
Deafwave
- If Callback is a function, it is called with one parameter, the name of the hotkey.
Hotkey("F1", "createMessageBox")
Return
createMessageBox(hotkey) {
global
MsgBox hotkey
Return
}
- Parameter must be a string, also now & is not used for address, instead StrPtr and ObjPtr are used:
defaultObject := {
testVar: "yay, it worked"
}
CritObj := CriticalObject(defaultObject)
additionalThread := "
(
CritObj := CriticalObject(A_Args[1])
CritObj.testVar := "Manipulated CritObj String"
MsgBox(CritObj.testVar)
)"
exampleThread := AHKThread(additionalThread, "" ObjPtr(CritObj), "testSecondThread", false)
Sleep(2000) ; Janky Test
MsgBox CritObj.testVar
Return
I have also updated Ahk2Exe.exe in compiler (using v1) in the downloads and fixed not to add Exit in the end of script.
I see you have been making documentation updates, but I did not see anything on this last remaining issue.
Q: When I compile the script with includes, what is the proper way to start an AHKThread?
My working out:
https://github.com/Deafwave/ahkdll-v2-release/tree/testCompiler/src
Primary File:
; src/exampleOne.ahk
defaultObject := {
testVar: "test failed"
}
CritObj := CriticalObject(defaultObject)
;;;;;;;;
; Non-compiled: MessageBox with "Manipulated CritObj String"
; Compiled: Script File Not Found exampleTwo.ahk
exampleThread := AHKThread(A_ScriptDir "\exampleTwo.ahk", "" ObjPtr(CritObj), "exampleTwo", true)
;;;;;;;;
; Non-compiled: MessageBox with "Manipulated CritObj String"
; Compiled: Function library not found #include <exampleLibrary>
#include <exampleThree>
exampleThread := AHKThread(exampleThreeString, "" ObjPtr(CritObj), "exampleThree", false)
; addFile appears to be the same issue
; BinRun might work, but then I'd have to compile two or more .exe's and I'd prefer to package it into a single
;;;;;;;;
Sleep(2000) ; Jank Test
Return
You should use CreateScript to include script in your Compiled exe that is then used by AhkThread, see this post: https://www.autohotkey.com/boards/viewtopic.php?p=373780#p373780
We're close! I tried many different variations and attempted bypasses, the closest ones I found have been pushed to the same repo: https://github.com/Deafwave/ahkdll-v2-release/blob/testCompiler/src/exampleOne.ahk
I'm unsure of the difference between DynaRun() as shown in the documentation, and AhkThread(), but I followed the example you provided in the aforementioned post.
- All of my semi-working variations have one error after compilation, 0 before.
; Non-compiled: Working as Expected
; Compiled: Warning: This variable has not yet been assigned a value Specifically local aScript at L#73 @ https://i.imgur.com/3f2GasX.png
exampleThread := AHKThread(CreateScript("ExampleTwoMemory:ExampleTwoMemoryEnd"), "" ObjPtr(CritObj))
- Placing a return after the label as you did in the aforementioned post, causes the code to not execute due to hitting a return. I have 'bypassed' this by placing a placeholder variable:
;; Seems to cause strange Return issues, probably because of my bypass placeholder
ExampleTwoMemory:
placeholder := "So label isn't looking at a function, and is not a return to prevent code execution"
#include <exampleTwoLib>
ExampleTwoMemoryEnd:
Return
- Specifically to the non-label function style as per the documentation, it has an additional error, and a slightly different placement of the local aScript issue.
;; Non-compiled: Nothing happens
;; Compiled: Warning in #include file "CreateScript.ahk"
;; This variable has not been assigned a value
;; Specifically: local aScript (L#27) @ https://i.imgur.com/9DThmyq.png
;; Missing "}" somewhere
exampleThread := AHKThread(CreateScript("ExampleTwoMemory{}"), "" ObjPtr(CritObj))
Please let me know if you would like me to open additional issues for any of these findings.
Thanks,
Deafwave
aScript issue is solved, download again.
If the #include only contains function or classes you can simply place it in the end, then return is not a problem: AhkThread(MyScript "`n" CreateScript("ExampleTwoMemory:ExampleTwoMemoryEnd"), "" ObjPtr(CritObj))
I appear to be receiving this new error on all five compiled variations: https://i.imgur.com/ei3mTEb.png
Error: This value of type "String" has no property named "Ptr".
--
This variant still remains elusive when executing as source: https://i.imgur.com/7YbdMcI.png
It appears to remove MessageBoxFunction(string)
in exampleLibrary.ahk causing this issue.
exampleThread := AHKThread(CreateScript("ExampleTwoMemory{}"), "" ObjPtr(CritObj))
ExampleTwoMemory() { ; Error: Missing "}"
placeholder := "So label isn't looking at a function, and is not a return to prevent code execution"
#include <exampleLibrary> ; Appears to nuke "MessageBoxFunction(string) " causing
#include <exampleTwo>
}
The first error is because UnZipRawMemory could not extract script, did you compile with encryption, then you need to pass the passwort to CreateScript.
The lookup for end of function is not very smart, so it finds the ending bracket before end, better to stick with Labels or indent code in your library.
I believe I did not compile with Encryption, or if I did, I used the default password.
I will validate this, but as shown in #17 I used:
RunWait "`"D:\ahkdll-v2-release\Compiler\Ahk2Exe.exe`" `"D:\ahkdll-v2-release\Compiler\Ahk2Exe.ahk`" /in `"D:\ahkdll-v2-release\src\exampleOne.ahk`" /out `"D:\ahkdll-v2-release\src\compiled\exampleOne.exe`" /bin `"D:\ahkdll-v2-release\x64w\AutoHotkey.exe`" /compress 1"
That being said, in the future I will use Encryption, but I do not see where the password would go in the RunWait. Save Script Settings As
does not appear to save the Encrypt command/password to the file.
I attempted to compile via the AHK2Exe instead of through the RunWait. I received this error.
Error: The Script contains syntax Errors.
Specifically: CreateScript.ahk
Can find the error here: https://i.imgur.com/izngAPg.png
Try again with latest release.
If you use encryption the default password is AutoHotkey, so it would be CreateScript("ExampleTwoMemory{}","AutoHotkey").
Otherwise leave empty.
If you don't use encryption and compression, you can extract script from exe using ResHacker and debug to see what the problem is.
Otherwise provide simple example that reproduces the problem and I will take a look.
Ah! Noted, let me take another look.
- Immediate Error upon executing latest AHK2Exe.exe: https://i.imgur.com/WDE1KIW.png
; File: DynaRun.ahk
; This is a pain to debug since it's a string format.
illegal character "UChar""
Passed it by updating to:
NumPut(`"`"UChar,`"`"0x h,dmp,A_Index/2-1)
Based on how https://github.com/HotKeyIt/Ahk2Exe/blob/master/Lib/DynaRun.ahk looked, it should be a variable, not a string? However, my knowledge in this area is limited and untested, so I will not submit a PR.
New error: https://i.imgur.com/dPBuNKK.png
Call to nonexistent function.
Specifically: BufferAlloc
I believe this is casued by the Hybrid v1 -> v2.
BufferAlloc() is a function in v2, but is VarSetCapacity() in v1 with a very different input style. I can attempt to downgrade to VarSetCapacity, but I believe that would not be beneficial for us to move forward. I'll wait for your knowledge.
I have cleaned up an extremely basic testing directory for this repo.
https://github.com/Deafwave/ahkdll-v2-release/tree/testCompiler
It currently contains two tests that work as expected when uncompiled and fail to compile due to the aforementioned errors.
Please let me know if you would like me to make this a Pull Request.
Sorry I should have thought about that, try latest release.
No problem, I appreciate you working with me to get this resolved.
Good news is the Non-encrypt method via Ahk2Exe.exe UI is working as expected.
I am unsure how the password gets stored using /NoDecompile
in the CLI version so the following attempts were all done with the UI.
That being said, compress or encrypt is breaking compilation still: https://i.imgur.com/ZJ4vVbA.png
Error: This value of type "string" has no property named "Ptr".
; testFuncEncrypt.ahk
; UI: Compress with MPRESS or UPX -> aforementioned error
; UI: Compress with MPRESS or UPX + encrypt of `AutoHotkey` via UI -> aforementioned error
; UI: No Compress, No Encrypt -> Runs as Expected
exampleThread := AHKThread(CreateScript("ExampleFourMemory:ExampleFourMemoryEnd", "AutoHotkey"), "" ObjPtr(CritObj))
; testFunc.ahk
; UI: Compress with MPRESS or UPX -> Compiled runs, does nothing
; UI: Compress with MPRESS or UPX + encrypt of `AutoHotkey` via UI -> Compiled runs, does nothing
; UI: No Compress, No Encrypt -> Runs as Expected
exampleThread := AHKThread(CreateScript("ExampleFourMemory:ExampleFourMemoryEnd"), "" ObjPtr(CritObj))
CLI for password is
/pass AutoHotkey
I finally found the problem with CreateScript, it should work fine now.