AutoHotkey_L Fork With Improved Debugging Support

Post your working scripts, libraries and tools for AHK v1.1 and older
Wade Hatler
Posts: 60
Joined: 03 Oct 2013, 19:49
Location: Seattle Area
Contact:

AutoHotkey_L Fork With Improved Debugging Support

06 Dec 2013, 14:12

AutoHotkey_L++ (more like L += .0001)

I have created a small fork of AutoHotkey_L for experimental purposes with several new debugging features. I hope to merge the code back into the main branch after more testing. The REAL AutoHotkey is the Lexikos Version on GitHub.

All my changes are geared around better debugging, troubleshooting and logging support. I'm building a commercial product with this (in fact, I'm building my whole company with it), so I use it all day every day and it's stable for me.

Please report any issues via the GitHub Repository, or the forum thread – or just fork it and fix it ;)

At the moment I only have ANSI builds, but I'll fix the Unicode builds soon (or you are welcome to do so). I also have not updated the documentation yet.

How to Use
It's easy to try this out. The AutoHotkey installer places a backup copy of the original files in your AutoHotkey folder, so it's easy to revert back by simply overwriting a file. If you use the installer, you should find AutoHotkeyA32.exe and AutoHotkeyW32.exe in your AutoHotkey folder. The installer copies one of those files to AutoHotkey.exe based on which option you choose during installation, but you can switch from one to the other by simply overwriting AutoHotkey.exe with the version you want (after closing all scripts), or you can run different scripts with different versions by running the specific executable you want for a particular script.

To test this version, you can save it as AutoHotkey.exe and use it for everything (what I do), or you can save it to a temp file rename it, and then only run it when you want to test my changes. Either way works fine, and you can always revert by simply copying the correct original file to AutoHotkey.exe.

Download the executable from my web site and either overwrite AutoHotkey.exe or save it in a temp folder, rename it and move it into the main AutoHotkey folder. Whether you keep it as AutoHotkey.exe or rename it to something like AutoHotkeyBonzai.exe, it should be in the AutoHotkey folder so script variables like A_AhkPath work as expected.

Stack Trace for All Exceptions

All internal exceptions and those thrown using the Exception object, now include a .StackTrace field that shows the stack trace back to the beginning of execution, similar to .NET or Python. For example, this sample calls a label, which calls a function, which throws an internal exception:

Code: Select all

try {
    Gosub RunMe
    ExitApp
} catch ex {
    CrashException("Uncaught Exception", ex)
}

RunMe:
    CDD("\BOGUS")
    return

CDD(Folder) {
    SetWorkingDir %Folder%
}
The exception thrown by SetWorkingDir looks like:

Code: Select all

Message: 1
What   : SetWorkingDir
File   : C:\Temp\TestException.ahk
Line   : 16
Stack  : 
File                      Line: Context Code
C:\Temp\TestException.ahk   17: CDD()   SetWorkingDir %Directory%
C:\Temp\TestException.ahk   12: RunMe:  CDD("\BOGUS")
C:\Temp\TestException.ahk    5: RunMe:  Gosub,RunMe
The first line of the stack trace lists the source line the exception happened on, or sometimes the line before or after depending on how the exception happened. The lines below show the call stack back to the start of the program, with every gosub or function call creating one entry.
  1. The first two columns are self-explanatory.
  2. Context is the method or label active at the time of the exception. For example, the last 2 lines are both from the RunMe: label. Labels end in : and functions end in ()
  3. Code is the first 80 or so characters of the internal AHK version of the code after parsing. It usually matches the code without comments or whitespace. Multi-line statements are concatenated.
In the examples, CrashException is an AHK Function from my standard AHK Library that just formats the exception nicely and displays it in a debug dialog. It just produces the message you see in the second box. This is the pattern I use on all my programs. I want all exceptions caught and reported, so I have a small header file that inserts the lines above ending with RunMe, and I put that at the top of every AHK script. I'll publish it after a little more cleanup.

At the moment, this only works with internally thrown exceptions and exceptions thrown using the Exception object, so your exceptions you generate yourself in try/catch blocks should look like:
Throw Exception("This is Bogus", -1)
Instead of
Throw "This is bogus"
The format of the Stack Trace is suspiciously similar to compiler errors, and you can pretty easily make most code editors take you right to the line. I've done so for Visual SlickEdit, but not for others. You can probably convert it to any editor format you like with a few lines of AHK code.


Additional Information in Exceptions with A_LastError

For internal commands that set A_LastError (e.g. FileDelete, etc.), a new LastError field is added to the Exception object. This field is formatted as ErrorCode = Error Description where Error Description is obtained from the FormatMessage API call (which is usually but not always right), and ErrorCode is just a copy of A_LastError. If you want to process the numeric part, you can just use A_LastError which will always match the numeric part of the error, or parse the numeric part with a Regex.

For example, if you try to delete a read-only file, it returns an exception object something like:

Code: Select all

Message  : 1
What     : FileDelete
File     : C:\Palabra\AutoHotkey_L\Tests\AhkCompilerTest.ahk
Line     : 149
LastError: 5=Access is denied.
Stack    : 
File                       Line: Context                    Code
C:\...\AhkCompilerTest.asx  148: Test_Exception_LastError() FileSetAttrib,+R,%TestFile%
C:\...\UnitTest.ahk         324: TestRunAll()               Func(functionName).()  
C:\...\AhkCompilerTest.asx   23: RunMe:                     TestRunAll()  
C:\...\AhkBase.ahk           13: RunMe:                     Gosub,RunMe
This one isn't perfect, because I haven't gone back and cleared A_LastError in all functions that don't use it, so some exceptions will show a nonsense LastError field from the last error that happened to occur, even if it wasn't in the current statement. I'll be adding code to clear this in a later release.

Improvements to ListLines
I added several improvements to ListLines because it seldom has enough information to really be useful. This was the first change I made, although now that I've added the stack trace mentioned above I don't use it as much as I once did.

ListLines, File
If you pass a file name as the first parameter to ListLines, the lines are dumped directly to the file and the UI never shows up. You can then open the file and process it any way you like. The command is synchronous, so you can follow it with the command to process the file. If you want to do more detailed preprocessing of the lines, just write the AHK code to scan through the file and make any changes you like. See below for formatting details that are useful for processing the file.

Code: Select all

    ListLines, %A_Temp%\ListLines.ahk
ListLines, Clear
You can clear the current line list anytime you like, which is useful after you've loaded up some massive libraries you don't really want in your debug output.

Code: Select all

    ListLines, Clear
A_ListLines
The new built-in variable A_ListLines returns the current ListLines state. 1=On, 0=Off. You can use it to save/restore the state.

Code: Select all

WasListing := A_ListLines
ListLines, Off
...
ListLines %WasListing%
ListLines, True/False
You can now set ListLines state with True/False in addition to "On"/"Off". This makes it easier to save/restore the state of ListLines.

ListLines Cleanup
I added some features to make the lines easier to read and process.
  1. Line numbers always have four digits so they line up well for readability.
  2. The total number of lines that can show up in a file has been increased from 400 to 4000. Note that the original limit of 400 was caused by the ListLines GUI, so the GUI still only shows 400 lines.
  3. Filenames in the list have a ; at the start. If you list them to a file and open them in an editor with AHK support, they'll show up as comments, which makes them stand out more. Of course the lines themselves are just AHK code so they'll be color coded as well.
lexikos
Posts: 9589
Joined: 30 Sep 2013, 04:07
Contact:

Re: AutoHotkey_L Fork With Improved Debugging Support

06 Dec 2013, 18:10

Wade Hatler wrote:This one isn't perfect, because I haven't gone back and cleared A_LastError in all functions that don't use it, so some exceptions will show a nonsense LastError field from the last error that happened to occur, even if it wasn't in the current statement. I'll be adding code to clear this in a later release.
It would be inappropriate to have commands which don't set A_LastError clear it, not least of all because it would break some scripts. Instead, I would suggest including the LastError field only when it is relevant.
Wade Hatler
Posts: 60
Joined: 03 Oct 2013, 19:49
Location: Seattle Area
Contact:

Re: AutoHotkey_L Fork With Improved Debugging Support

06 Dec 2013, 18:20

That makes sense. It will take more changes to the code than I was hoping for, but they're all low risk changes and your suggestion is better. I'll do it when I fix Unicode and 64bit.

Thanks,
User avatar
trismarck
Posts: 506
Joined: 30 Sep 2013, 01:48
Location: Poland

Re: AutoHotkey_L Fork With Improved Debugging Support

09 Jan 2014, 06:51

Hello Wade,

I'd like to test this, but it appears that the link to the executable is broken. Could it be updated?
vasili111
Posts: 747
Joined: 21 Jan 2014, 02:04
Location: Georgia

Re: AutoHotkey_L Fork With Improved Debugging Support

21 Jan 2014, 02:38

It will be also nice if you add command that will show stack like "SciTE4AutoHotkey". It can have name like "ListStack" and should have output method in a way like "ListVars" command have.
DRAKON-AutoHotkey: Visual programming for AutoHotkey.
Wade Hatler
Posts: 60
Joined: 03 Oct 2013, 19:49
Location: Seattle Area
Contact:

Re: AutoHotkey_L Fork With Improved Debugging Support

31 Jan 2014, 19:19

My apologies for the long delay in replying. Looks like I wiped that folder out when I rebuild my website. I've reuploaded it, so go to the very first message in this thread and grab the link from there. Everything is as described in that post, including only ANSI support and some superfluous error messages in some of the exceptions (because I report A_LastError and never clear it).

You can get the runtime stack by generating an exception manually, and then picking the call stack out of the .Stack field.

Code: Select all

MsgBox % Exception("").Stack
The format of the stack exceptions looks suspiciously like SlickEdit error files, but they're easy to transform into another format if you need it for a different editor. I never quote the filenames even if they have spaces, so the line is quite easy to parse with a regular expression. This code breaks it up into four fields, and then you can recombine them in any format you like.

Code: Select all

    Stack := Exception("").Stack
    Loop, parse, Stack, `n
    {
        if (A_Index == 1 || !A_LoopField)
            continue
        Regexmatch(A_LoopField, "O)^(?'file'.*?) +(?'line'\d+): +(?'what'.*?(\(\)|:)) +(?'msg'.*)", R)
        MsgBox % "File: " R.file "`nLine: " R.Line "`nWhat: " R.what "`nMsg: " R.Msg
    }
Give it a try and let me know what you think.
User avatar
trismarck
Posts: 506
Joined: 30 Sep 2013, 01:48
Location: Poland

Re: AutoHotkey_L Fork With Improved Debugging Support

04 Feb 2014, 13:21

Thanks Wade. I've currently drifted away from testing exceptions but I hope to get back to it. For now, I've downloaded the executable so that the whole puzzle is in one place. To be continued...

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: ntepa and 151 guests