脚本调试辅助器

许多实用脚本和封装函数, 可以让您编写脚本更加便捷高效

Moderators: tmplinshi, arcticir

User avatar
amnesiac
Posts: 186
Joined: 22 Nov 2013, 03:08
Location: Egret Island, China
Contact:

脚本调试辅助器

29 Sep 2014, 03:45

导言:有多少朋友看过之前发的「脚本主窗口的妙用」?请在后面留言,同时说说看过后自己的收获。那篇说的感觉有点凌乱,似乎能用上的场合也很少,如果你想知道我的收获,那么这就是我接着要开始说的内容了。在写脚本过程中,调试改错的时间可能占了一大部分,其中包含了检查静态代码和动态运行观察。对于大多数用户,观察动态运行时大都使用常规的调试方法,要在脚本运行过程中查看执行的代码、变量的内容或热键等要么通过托盘菜单打开,要么在脚本中另外定义热键打开。这两种方法虽说不上特别麻烦,例如对于托盘图标若多运行几个脚本就需要先看提示才能找到,而定义热键则需先在脚本中定义不说还必须记住,若同时调试几个脚本,用什么热键都要琢磨点时间。以前的文章中我曾提到这些调试热键:

Code: Select all

Pause::Pause
^!s::Suspend
^!r::Reload
^+q::ExitApp
!l::ListLines
!v::ListVars
!k::KeyHistory
实际上我自己都没记住,真是袈裟未着愁多事,着了袈裟事更多。就不能简单一点吗?下面介绍脚本调试辅助器。
功能展示
2014-09-29 14 18 10.png
「脚本调试辅助器」界面
主要功能一目了然,在选中脚本后点右边的按钮执行相应的操作。原理在「脚本主窗口的妙用」中说过,由于通过隐藏窗口检测,所以不论脚本是否使用自定义图标、是否隐藏托盘图标等都不会影响操作。

使用说明及注意事项
  • 若运行时提示错误,请下载安装最新的 AutoHotkey 版本。
  • 在操作脚本前,建议先刷新,程序在操作前不会去判断脚本是否存在或处于哪种状态(可能从外部被修改了)。
  • 尽管可以检测到编译后的脚本,但某些功能不起作用。
最后,感谢 Lexikos 提供远程获取脚本状态的方法

同类的工具
经朋友提醒,才知道碰车了。前期的搜集工作做的还不够充分,重复造轮子。

Lexikos 的 AHKControl
AHKControl.png
AHKControl 用法演示
调试功能相同,可调节的选项较多,它这里使用菜单的形式,欢迎大家选择。

Scriptcontrol 1.2
ScriptControl.png
Script Control 界面
功能较简化,若用于调试可能不够方便。

扩展说明
这个工具很小,不到 200 行代码,总体而言较为紧凑。思路明确,我想较容易理解和扩展(比起同类工具这点算优势吧),欢迎大家根据自己的需求添加代码。

Code: Select all

/*
http://ahkscript.org/boards/viewtopic.php?f=28&t=4721
Script Name: ScriptManager.ahk
Version: 0.1.00.12
Author: amnesiac

若无法运行,请下载安装最新的 AutoHotkey 版本。
这是测试版,不保证所有功能都能正常使用,请自负风险。
在操作脚本前,建议先刷新,程序在操作前不会去自动判断脚本是否存在或处于哪种状态(可能从外部被修改了)。
*/
#NoEnv
SetTitleMatchMode 2
DetectHiddenWindows On
SetWorkingDir, %A_ScriptDir%
Menu, Tray, Icon, Shell32.dll, 81
WM_COMMAND := 0x111
; 下面这些消息号提取自 AutoHotkey_L 源代码。
ID_FILE_RELOADSCRIPT := 65400
ID_FILE_EDITSCRIPT := 65401

ID_FILE_PAUSE := 65403
ID_FILE_SUSPEND := 65404
ID_FILE_EXIT := 65405
ID_VIEW_LINES := 65406
ID_VIEW_VARIABLES := 65407
ID_VIEW_HOTKEYS := 65408

ThisWndName := "脚本调试辅助器"
ThisVersion := "0.1.00.12"
ThisAuthor := "amnesiac"

MyAhkVersion := "AutoHotkey " (A_IsUnicode ? "Unicode" : "ANSI") " " ((A_PtrSize = 4) ? "32-bit" : "64-bit" ) " " A_AhkVersion

gosub, CreateGUI
gosub, RefreshList
gosub, UpdateSB
return

CreateGUI:
Gui +LastFound
Gui, Font, s10
Gui, Add, GroupBox, x452 ym w100 h180 , 查看
Gui, Add, Button, x462 y20 w80 r1 gOperateScript vID_FILE_EDITSCRIPT, 编辑(&E)
Gui, Add, Button, x462 y60 w80 r1 gOperateScript vID_VIEW_LINES, 历史(&L)
Gui, Add, Button, x462 y100 w80 r1 gOperateScript vID_VIEW_VARIABLES, 变量(&V)
Gui, Add, Button, x462 y140 w80 r1 gOperateScript vID_VIEW_HOTKEYS, 热键(&K)
Gui, Add, GroupBox, x452 y190 w100 h180 , 操作
Gui, Add, Button, x462 y210 w80 r1 gOperateScript vID_FILE_PAUSE, 暂停(&P)
Gui, Add, Button, x462 y250 w80 r1 gOperateScript vID_FILE_SUSPEND, 挂起(&S)
Gui, Add, Button, x462 y290 w80 r1 gOperateScript vID_FILE_RELOADSCRIPT, 重启(&R)
Gui, Add, Button, x462 y330 w80 r1 gOperateScript vID_FILE_EXIT, 退出(&X)
Gui, Add, ListView, xm ym+10 w430 +R20 AltSubmit gThisLVSub HwndThisLVHwnd, 窗口句柄|脚本名|暂停|挂起|脚本路径
Gui, Add, Button, x62 y400 w80 r1 gSelectAll, 全选(&A)
Gui, Add, Button, x162 y400 w80 r1 gInvertSelection, 反选
Gui, Add, Button, x262 y400 w80 r1 gSelectNone, 不选
Gui, Add, Button, x362 y400 w80 r1 gRefreshList, 刷新
Gui, Add, Button, x462 y400 w80 r1 gAboutScriptManager, 关于
Gui, Add, StatusBar
SB_SetParts(120, 120)
SB_SetText(MyAhkVersion, 3)

Gui, Show, AutoSize, %ThisWndName% %ThisVersion% by %ThisAuthor%
return

GuiClose:
ExitApp

OperateScript:
RowNumber := 0
Loop, % LV_GetCount("Selected")
{
    RowNumber := LV_GetNext(RowNumber)
    if !RowNumber
        break
    LV_GetText(CurrentWnd, RowNumber, 1)
    CurrentCommand := %A_GuiControl%
    PostMessage, %WM_COMMAND%, %CurrentCommand%,,, ahk_id %CurrentWnd%  
}
if (A_GuiControl = "ID_FILE_RELOADSCRIPT")  
    Sleep, 500
gosub, RefreshList
gosub, UpdateSB
return

SelectAll:
LV_Modify(0, "Select")  
gosub, UpdateSB
return

InvertSelection:
Loop % LV_GetCount()
{
    wParam := A_Index - 1
    SendMessage, 0x102C, %wParam%, 0x2,, ahk_id %ThisLVHwnd% 
    if ErrorLevel
        LV_Modify(A_Index, "-Select")
    else
        LV_Modify(A_Index, "Select")
}
gosub, UpdateSB
return

SelectNone:
LV_Modify(0, "-Select")  ; 取消选择所有。
gosub, UpdateSB
return

RefreshList:
LV_Delete()
WinGet, AHKWinList, List, ahk_class AutoHotkey 
Loop, %AHKWinList%
{
    
    AHKWinHWND := AHKWinList%A_Index%
    
    WinGetTitle, AHKWinTitle, ahk_id %AHKWinHWND%
    ScriptPathName := RegExReplace(AHKWinTitle, " - AutoHotkey v[\d.]+?$")
    SplitPath, ScriptPathName, ScriptName, ScriptDir
    LV_Add("", AHKWinHWND, ScriptName, IsPaused(AHKWinHWND), IsSuspended(AHKWinHWND), ScriptDir)
}
LV_ModifyCol(1, "Integer Sort") 
LV_ModifyCol()
gosub, UpdateSB
return

AboutScriptManager:
MsgBox, 4160, 关于, 感谢使用,在使用过程中遇到问题或有相关建议请至官方论坛反馈。`n官方论坛网址(中文版在下方):http://ahkscript.org/boards/
return

ThisLVSub:
UpdateSB:
RowNumber := SeletedNum := 0
Loop, % LV_GetCount("Selected")
{
    RowNumber := LV_GetNext(RowNumber)
    if !RowNumber
        break
    SeletedNum++
}
SB_SetText("已选脚本数:" SeletedNum, 1)
SB_SetText("总脚本数:" LV_GetCount(), 2)
return

; SKAN: http://www.autohotkey.com/board/topic/30277-/#entry192925
; Lexikos: http://www.autohotkey.com/forum/viewtopic.php?p=142697#142697
IsPaused(hWnd) {
    static MF_CHECKED := 0x8
    static WM_ENTERMENULOOP := 0x211
    static WM_EXITMENULOOP := 0x212
    SendMessage, WM_ENTERMENULOOP,,,, ahk_id %hWnd%
    SendMessage, WM_EXITMENULOOP, ,,, ahk_id %hWnd%
    hMenu := DllCall("GetMenu", "uint", hWnd)
    hMenu := DllCall("GetSubMenu", "uint", hMenu, "int", 0)
    return (DllCall("GetMenuState", "uint", hMenu, "uint", 4, "uint", 0x400) & MF_CHECKED) && true
}

IsSuspended(hWnd) {
    static MF_CHECKED := 0x8
    hMenu := DllCall("GetMenu", "uint", hWnd)
    hMenu := DllCall("GetSubMenu", "uint", hMenu, "int", 0)
    return !!(DllCall("GetMenuState", "uint", hMenu, "uint", 5, "uint", 0x400) & MF_CHECKED)
}
补充说明
我曾介绍过编辑器、窗口控件检测工具等,而 AutoHotkey 脚本管理器也是 AutoHotkey 工具链中的一环(换句话说我可能会把这个工具往管理器方向扩展),如果你有经常使用的工具希望加入其中,请到官方论坛提起建议并补充相关说明。

参考过的脚本
在写之前曾收集过下列脚本,这里一并致谢(按时间先后顺序排列):
统一管理AHK脚本
AHK Script Manager – AHK 脚本管理器
Script Manager
Axem - AutoHotKey Scripts Manager
autohotkey-script-manager 一款用于管理常用ahk脚本运行的桌面工具
我最初想写的是管理器,写到现在的功能后发现,主要和调试有关,所以改为「调试辅助器」。
再补充一个:AutoHotkey-ToolKit
AutoHotkey 学习指南(Beauty of AutoHotkey)
I do not make codes, and only a porter of AutoHotkey: from official to Chinese, from other languages to AutoHotkey, and show AutoHotkey to ordinary users sometimes.
User avatar
RobertL
Posts: 546
Joined: 18 Jan 2014, 01:14
Location: China

Re: 脚本调试辅助器

29 Sep 2014, 04:07

看完贴,慢慢学习,先谢过了。
我为人人,人人为己?
driftcrow
Posts: 1
Joined: 12 Oct 2014, 20:21

Re: 脚本调试辅助器

12 Oct 2014, 20:25

眼睛不太好使了,看了半天没看到下载 的点:(

最后终于看到了,谢谢
cixiplc
Posts: 8
Joined: 18 Oct 2014, 15:52

Re: 脚本调试辅助器

03 Apr 2015, 05:39

mark
xuezhe
Posts: 91
Joined: 06 Jan 2016, 11:02

Re: 脚本调试辅助器

28 Jan 2016, 23:50

过来看看不错的样子。
hitman
Posts: 21
Joined: 10 Aug 2014, 06:47

Re: 脚本调试辅助器

06 Dec 2017, 21:11

向前辈致敬
User avatar
miozus
Posts: 15
Joined: 08 Sep 2021, 21:53

Re: 脚本调试辅助器

08 Sep 2021, 22:32

:shock: 七年过去了;再看这个功能还是可以的。

推荐另一种简单的思路:

主脚本 + 其他插件脚本,用 #include 组合起来

只用一次重载,全部更新。

示例

Code: Select all

CapsLock & y:: 
    if GetKeyState("alt")  = 1
    {
        ; Edit
        Run,  "D:\TOOLS\Microsoft VS Code\Code.exe" "D:\TOOLS\AutoHotKey\CapslockPlus\CapslockPlus.ahk"
    }
    else if GetKeyState("ctrl") = 1
    {
        ; search for help
        Run, "https://wyagd001.github.io/zh-cn/docs/AutoHotkey.htm"
        send, !s
    }
    Else
    {
        if winExist("ahk_class AutoHotkey")
            WinActivate
        Else
        {
            ; 设计悬浮动画,再重载本脚本,因为重载太快,后面很难放出来
            ToolTip, ✔
            sleep, 400
            ToolTip
            Reload
        }
        return
    }
return


Return to “脚本函数”

Who is online

Users browsing this forum: No registered users and 10 guests