
简介AutoIt V3.3.6.1绿色汉化特别版是一份面向Windows自动化脚本初学者与运维、测试人员的免安装工具包围绕BASIC风格脚本编写与GUI自动化展开可用于模拟键鼠、窗口与控件操作、执行程序和读写注册表解决重复性批处理与桌面流程自动化问题。压缩包共194个文件大小约6.44MB其中129个au3脚本与函数库是核心示例和调用素材另有11个exe工具、lua与properties配置、api提示文件及帮助文档兼顾编写、调试和查阅。已有871人学习下载。读者可据此快速熟悉AutoIt v3的语法、标准库调用和SciTE编辑环境配置借助API提示与示例脚本理解窗口控件交互、批处理及ActiveX/DLL扩展用法并可将脚本编译为独立运行文件适合边学边改、搭建自己的自动化小工具。1. 解压即用的 AutoIt3MB 目录里装着什么能替你点掉哪些活内网那台只能远程进的机器没有部署接口也没有管理员配合你要做的却是把一套老客户端按七步向导点完中间点错一步就得从头再来。这种「只有界面、没有 API」的活AutoIt脚本圈里常写成 AU3是最省事的一把刀语法贴着 Basic 的路子走几行Run加WinWait把窗口等出来再用ControlClick把按钮按下去不用装运行时也不用配编译环境。V3.3.6.1 绿色汉化特别版给的是一个解压就能用的完整工具链——解释器、编译器、编辑器、窗口信息抓取工具和中文帮助全在一个目录里拷到 U 盘换台机器照样跑。它适合运维、测试、交付工程师处理重复的 Windows 界面操作不适合拿去做 Web 自动化或跨平台任务。2. 绿色包落地目录分工、编码设置与第一个能跑起来的脚本拿到压缩包很多人第一反应是双击 SciTE 就开始写结果脚本能编辑不能跑、跑了又乱码。绿色版省掉的是安装过程不是环境判断。先把目录里谁负责什么弄清楚后面所有排错都能少绕一半路。2.1 解压后的目录分工与三个隐式前提正常的绿色汉化包解压出来大致是这样一套结构不同打包者会合并或改名但核心几件不会少路径作用什么时候会用到Au3.exe脚本解释器直接运行.au3调试阶段用Au3Info.exe/Au3Info_x64.exe窗口信息抓取抓窗口标题、控件 ID、坐标Aut2Exe/Aut2Exe.exe编译器把脚本打成独立 exeSciTE/SciTE.exe编辑器写脚本、F5 运行、CtrlF7 编译Include/UDF 扩展库#include File.au3这类引用Examples/官方示例抄窗口、GUI、文件操作的写法Icons/图标资源编译时给 exe 换图标中文帮助.chm函数手册查参数比搜网页快先把关键组件点一遍确认包是完整的别等到写完脚本才发现缺编译器echo off :: 在解压目录根部执行检查核心组件是否齐全 for %%F in (Au3.exe Au3Info.exe Aut2Exe\Aut2Exe.exe SciTE\SciTE.exe) do ( if exist %%~fF (echo [OK] %%F) else (echo [MISS] %%F) ) if exist Include\File.au3 (echo [OK] Include) else (echo [MISS] Include) pause这段批处理用的是for的文件遍历%%~fF把相对路径展开成绝对路径再判断比一行行if exist好维护。跑完看到[MISS]就别急着往下走压缩包多半被杀软啃掉了Aut2Exe重新解压并把目录加进白名单。三个隐式前提得提前说清。第一AutoIt 必须有桌面会话脚本要跟窗口打交道扔进没有交互桌面的服务里跑WinWait永远返回 0。第二解释器和编译产物都是原生程序不依赖 .NET、不依赖 VC 运行库这正是它能塞进 U 盘到处跑的原因但也意味着它不会帮你做任何环境适配。第三绿色版不写注册表.au3文件不会自动关联运行方式要么把脚本拖到Au3.exe上要么命令行Au3.exe your.au3要么在 SciTE 里按 F5。用哪个都行我一般在调试期用 SciTE交付前才编译。2.2 汉化界面与脚本编码乱码从来不是玄学汉化包做的事主要是替换 SciTE 的语言文件和附带中文帮助。如果打开编辑器菜单还是英文八成不是汉化失败而是你启动的 SciTE 读的是另一份配置——SciTE 会优先加载同目录下的locale.properties找不到才回落到内置英文。检查这个文件里有没有中文语言项比重新下一份包快得多。真正容易翻车的是脚本文件的编码。AutoIt3 的解析器对 Unicode 的支持是有条件的带 BOM 的 UTF-8 能认不带 BOM 的中文注释和中文路径就可能变成一堆问号。我踩过的坑很典型——脚本在本地跑得好好的拷到另一台机器上路径里的中文目录名全乱了FileExists一律返回 False。后来统一成两条规矩; 规则一路径不写死全部用宏拼 Local $sWorkDir ScriptDir \data Local $sLogFile $sWorkDir \run.log If Not FileExists($sWorkDir) Then DirCreate($sWorkDir) ; 规则二需要输出中文时显式指定编码 Local $hFile FileOpen($sLogFile, 2 128) ; 2覆盖写, 128UTF-8 FileWriteLine($hFile, 开始时间 YEAR - MON - MDAY) FileClose($hFile)ScriptDir是脚本自身所在目录的宏编译成 exe 后指向 exe 所在目录这样打包分发不会因为盘符变化而失效。FileOpen的第二个参数是标志位组合2表示写入模式并清空原内容128表示以 UTF-8 写出不加这个标志中文写进日志就是乱码。至于脚本文件本身最省事的做法是保存为 ANSIGBK中文注释和中文常量都不会出问题如果团队要求统一 UTF-8那就保存成带 BOM 的 UTF-8别用「UTF-8 无 BOM」。提示改完编码后一定重新打开一次文件确认某些编辑器会在保存时悄悄去掉 BOM你以为改了其实没改。2.3 第一个能跑的脚本Run、WinWait、ControlSetText 三件套别一上来就写复杂流程先用记事本验证「启动—等待—输入—关闭」这条链路通不通。链路通了后面换成任何业务软件都是同一套骨架。; demo_01.au3 —— 最小可运行链路 Opt(WinTitleMatchMode, 2) ; 2 标题包含匹配最宽松也最好用 Opt(WinWaitDelay, 100) ; 每次窗口操作后等 100ms给 UI 喘口气 Run(notepad.exe) ; 等待窗口出现第二个参数是窗口文本空串表示不校验 Local $hWin WinWait([CLASS:Notepad], , 10) If $hWin 0 Then MsgBox(16, 失败, 10 秒内没有等到记事本窗口) Exit 1 EndIf WinActivate($hWin) WinWaitActive($hWin, , 5) ; 直接给编辑框塞文本不依赖光标位置 ControlSetText($hWin, , Edit1, hello autoit 3.3.6.1) ; 关闭窗口并处理「是否保存」对话框 WinClose($hWin) Local $hDlg WinWait([CLASS:#32770], , 5) If $hDlg 0 Then ControlClick($hDlg, , Button2) ; Button2 一般是「不保存」 EndIf逐项说一下参数的含义这些是后面所有脚本的地基。Opt(WinTitleMatchMode, 2)把标题匹配模式切成「包含」也就是说写记事本就能命中「无标题 - 记事本」代价是误命中概率上升如果要做精确控制改成 3 或者用高级模式第 3 章展开。WinWait的第三个参数是超时秒数超时返回 0这是唯一可靠的失败信号所以每个WinWait后面都应该跟一个If $hWin 0判断而不是假设窗口一定出现。ControlSetText的第二个参数是窗口文本一般留空第三个参数Edit1是控件的 ClassNameNN不是固定值换一个软件就得用Au3Info重新抓。[CLASS:#32770]是 Windows 标准对话框的窗口类名保存确认、错误提示、UAC 之外的多数弹窗都是这个类值得记下来。Button2同理需要现场抓不同软件的按钮顺序不一样「不保存」不一定是 Button2。运行方式三选一把demo_01.au3拖到Au3.exe图标上命令行执行Au3.exe demo_01.au3或者用 SciTE 打开后按 F5。跑通之后你会看到一个窗口闪一下就没了这是正常的脚本执行速度快于人的感知。3. 窗口与控件定位Au3Info 抓不到控件时怎么退一步脚本写不下去九成卡在「找不到窗口」和「点不到控件」这两件事上。AutoIt 的定位体系分三层窗口靠标题/类名匹配控件靠标识符寻址动作靠消息投递或键鼠模拟。搞清楚每层的边界才知道什么时候该换下一层。3.1 变量与数据类型Variant 的方便和代价AutoIt 只有一种变量类型叫 Variant声明时不写类型赋值时自动判断。这带来了写脚本的爽快也埋了比较运算的坑——10 9在某些上下文里会按字符串比较得出 False。Local $iRetry 0 ; 数字 Local $sName setup ; 字符串 Local $bDone False ; 布尔 Local $aSteps[4] [解压, 安装, 配置, 校验] For $i 0 To UBound($aSteps) - 1 ConsoleWrite($i - $aSteps[$i] CRLF) Next ; 显式转成数字再比较避免字符串比较的坑 Local $sNum 10 If Number($sNum) 9 Then ConsoleWrite(数值比较正确 CRLF) ; 字符串拼接用 不是 Local $sPath ScriptDir \logs\ $sName _ YEAR MON MDAY .logLocal声明函数内局部变量脚本顶层用Global或直接赋值默认是全局容易污染建议一律显式写Local/Global。UBound($aSteps)返回数组长度减 1 才是合法下标这个-1忘了写就会数组越界。ConsoleWrite只在 SciTE 输出窗口或者编译成控制台程序时可见如果你的脚本是双击运行的 GUI 程序调试信息要改成写文件。CRLF、YEAR、ScriptDir这类以开头的是宏等价于系统常量用起来比函数调用轻。需要传引用的场景用ByRef比如让函数回填一个错误信息Func TryOpen($sPath, ByRef $sErr) If FileExists($sPath) Then Run($sPath) Return True EndIf $sErr 文件不存在 $sPath Return False EndFuncByRef意味着函数内修改会作用到调用方的变量上这是 AutoIt 里唯一的「多返回值」手段用多了会难读控制在错误信息、统计计数这类场景即可。3.2 窗口匹配五种模式和一个诊断组合WinTitleMatchMode有 1 到 4外加负数变体实际常用的就前四种值含义适用场景风险1从标题开头匹配标题固定的老软件标题加前缀就失效2标题包含子串标题带文件名、带版本号可能误命中同类窗口3标题完全相等精确定位标题一变就崩4高级模式支持 CLASS/REGEXPTITLE多语言、标题动态变化写法复杂调试成本高我默认用 2遇到「多个窗口标题都含同一段文字」时切到 4用窗口类名或正则把范围收窄Opt(WinTitleMatchMode, 4) ; 按窗口类名找标题随便变都不影响 Local $h1 WinWait([CLASS:Notepad], , 10) ; 按正则找适合标题里带时间戳、带文件名的场景 Local $h2 WinWait([REGEXPTITLE:(?i)安装.*向导], , 10) ; 类名 实例序号同进程开了多个窗口时用 Local $h3 WinGetHandle([CLASS:CabinetWClass; INSTANCE:2])写不出来的时候别猜用三个函数把现场信息打出来这是我排错的标准动作Local $h WinGetHandle([ACTIVE]) ; 当前活动窗口 ConsoleWrite(标题: WinGetTitle($h) CRLF) ConsoleWrite(类名: WinGetClassList($h) CRLF) ConsoleWrite(文本长度: StringLen(WinGetText($h)) CRLF) ConsoleWrite(坐标: WinGetPos($h)[0] , WinGetPos($h)[1] CRLF)WinGetClassList返回的是窗口内所有控件的类名清单一行一个配合Au3Info看能快速判断这个界面到底是不是标准控件。如果返回的清单很短或者全是Static说明这窗口大概率是自绘的标准控件接口点不动得看下一节。3.3 控件标识的三种写法和选择顺序Au3Info是这套工具里最有价值的一个 exe把准星拖到目标控件上右侧会显示Class、Instance、ID、Text四组信息。三种寻址方式各有适用面ClassNameNN形如Edit1、Button2表示「该类的第 N 个实例」。它对界面小改版不敏感是最常用的写法。ControlID一个整数是控件在窗口内的序号。它的优点是短缺点是极不稳定同一个软件换个版本ID 全变所以我基本不用。句柄用ControlGetHandle拿到控件的 HWND。它最精确但窗口重建后句柄失效适合在一次会话内多次操作同一个控件。Local $hWin WinWait([CLASS:Notepad], , 5) ; 写法一ClassNameNN ControlSetText($hWin, , Edit1, 第一段) ; 写法二先取句柄后续复用 Local $hEdit ControlGetHandle($hWin, , Edit1) If $hEdit 0 Then MsgBox(16, 失败, 没找到 Edit1界面可能改版了) Exit 1 EndIf ControlSetText($hWin, , $hEdit, 第二段) ; 读回内容做校验别假设写进去就一定成功 Local $sBack ControlGetText($hWin, , $hEdit) If $sBack 第二段 Then ConsoleWrite(写入未生效 CRLF)ControlGetHandle返回 0 是最常见的失败信号一定要判断否则后面的操作全部静默失败脚本看起来「跑了但没效果」。ControlGetText回读校验这一步很多人省掉结果在权限不足或者控件只读的情况下ControlSetText返回成功但内容没变白排查半天。如果控件是自绘的上面三招全失效退路有两条一是ControlClick传空字符串加坐标偏移也就是在窗口坐标系里点某个相对位置二是MouseClick用屏幕绝对坐标。两条路的共同问题是受分辨率和 DPI 影响第 5 章会细说。能用控件接口就不要用坐标这是原则。4. 编译成 exeAut2Exe 参数逐个拆与 UDF 引入路径脚本在自己机器上跑通只是完成了一半。交付给别人的时候对方机器上没有这套绿色目录你也不可能让业务方先去装个解释器。编译成独立 exe 是必走的一步而这一步的参数选错产物的行为会完全不一样。4.1 Aut2Exe 命令行参数与压缩级别的取舍SciTE 里按 CtrlF7 会调起图形界面的编译向导但要做批量构建或者写进流水线还是命令行靠谱:: 基础编译输入脚本输出 exe指定图标 Aut2Exe\Aut2Exe.exe /in demo_01.au3 /out demo_01.exe /icon Icons\app.ico :: 控制台版本带 ConsoleWrite 输出调试期用 Aut2Exe\Aut2Exe.exe /in demo_01.au3 /out demo_01_dbg.exe /console :: 最高压缩交付期用 Aut2Exe\Aut2Exe.exe /in demo_01.au3 /out demo_01.exe /comp 4/in和/out是必填项路径带空格要加引号。/icon只影响资源图标不影响运行。/console会生成一个带黑框的控制台程序ConsoleWrite的输出能看到代价是运行时多一个窗口正式交付时要去掉。/comp是压缩级别取值 0 到 4数字越大产物越小、启动时的解压开销越大我们这边一般用 4因为交付物走内网分发体积比那几十毫秒启动时间重要。还有个/pass可以给 exe 加启动密码内部工具用不上容易给自己找麻烦。如果目标机器是 64 位且需要调用 64 位系统接口绿色包里通常会带Aut2Exe_x64.exe用哪个编译器决定了产物的位数。这一点经常被忽略脚本里如果引用了WinAPI相关的 UDF32 位和 64 位的结构体对齐方式不同32 位下正常的代码换 64 位编译可能直接崩。4.2 #include 与 #pragma路径是绿色版最容易断的地方#include有两种写法语义完全不同#include File.au3 ; 尖括号从 Include 目录找 #include lib\mylib.au3 ; 双引号从脚本所在目录找尖括号的搜索路径依赖编译器自己推断 Include 目录的位置绿色版换台机器、换个盘符之后这个推断就可能失败报「找不到包含文件」。解决办法有两个要么把整个Include目录跟着脚本一起走保持相对位置不变要么在 SciTE 的配置文件里把openpath指到绝对路径。我一般选前者因为交付物要能自包含。#pragma是编译期指令写在脚本头部能覆盖命令行的一部分设置#pragma compile(Icon, Icons\app.ico) #pragma compile(Out, build\setup_tool.exe) #pragma compile(Compression, 4) #RequireAdmin ; 请求管理员权限 Opt(WinTitleMatchMode, 2)#RequireAdmin这条很关键它会在 exe 的清单里写入requireAdministrator双击时直接触发提权。很多脚本在开发机上手跑正常交付后「点不动任何按钮」就是因为目标窗口是高权限进程而脚本是普通权限第 5 章会展开这个坑。4.3 单文件分发能带走的和带不走的编译出来的 exe 是自包含的目标机器不需要装任何东西但有几样东西它不会自己带脚本里引用的外部文件、图标以外的资源、依赖的系统组件。所以打包前要做一次依赖体检; 打包自检列出脚本依赖的外部文件 Local $aDeps[3] [config.ini, driver\setup.exe, lib\helper.dll] For $i 0 To UBound($aDeps) - 1 If FileExists(ScriptDir \ $aDeps[$i]) Then ConsoleWrite([OK] $aDeps[$i] CRLF) Else ConsoleWrite([MISS] $aDeps[$i] CRLF) EndIf Next这段检查看起来简陋但比事后在客户现场发现少了个 dll 强得多。实际分发时我会把 exe 和这些依赖放在同一个目录打成压缩包解压即用路径全部用ScriptDir拼这样对方放哪个盘都能跑。还有一个绕不开的问题AutoIt 编译产物被杀软误报的概率不低。原因是它的产物结构是「解释器 加密脚本」这个特征和某些恶意程序的重打包方式撞了。这不是你能靠改代码解决的可行的做法是走内网白名单、给 exe 做代码签名证书企业内部分发一般有这个条件或者在文档里写清楚让运维加信任。指望换个压缩级别就能躲过去是浪费时间。5. 避坑排查昨天能跑今天不动八成是这五处脚本类故障的特点是不报错。窗口没等到函数返回 0你如果不判断整个流程就走空日志里干干净净看起来像什么都没发生。下面五条是我这几年返工次数最多的。5.1 手动双击正常计划任务里全失败现象同一个 exe手动双击跑得好好的挂到计划任务里日志只有第一行后面全没了。原因计划任务默认跑在非交互会话里没有可见桌面WinWait等不到任何窗口一路超时。如果任务配置成「不管用户是否登录都运行」这个问题必现。解决把任务的运行账户改成「只在用户登录时运行」并勾选「使用最高权限运行」。如果必须无人值守就不能用窗口自动化这套思路得换成命令行参数或者接口调用。这条没有绕过去的技术手段属于方案选型错误。5.2 目标窗口是管理员权限脚本点不动现象ControlClick返回成功界面毫无反应。ControlGetText能读到内容但写不进去。原因Windows 的 UIPI 机制禁止低完整性级别进程向高完整性级别进程发送窗口消息。你的脚本是普通权限目标程序是管理员权限消息被系统直接丢弃AutoIt 这一侧看到的是「调用完成」因为它拿不到对方的拒绝反馈。解决脚本头部加#RequireAdmin重新编译或者用管理员身份启动解释器调试。注意加了这个之后每次运行都会弹 UAC 确认框无人值守场景要配合计划任务的高权限配置。5.3 高分屏上坐标全偏控件坐标和屏幕坐标混用现象在 100% 缩放的开发机上正常到了 125% 缩放的笔记本上MouseClick点到了按钮外面。原因AutoIt 3.3.6.1 这个年代的程序不声明 DPI 感知系统会对它做坐标虚拟化而MouseClick用的是物理屏幕坐标ControlClick带偏移量用的是窗口客户区坐标两套坐标系混在一起必然错位。解决优先用ControlClick的控件寻址完全绕开坐标实在要用坐标就在目标机器上实测标定别用开发机的数值。另外可以调用系统接口把进程标成 DPI 感知让坐标系统一但这会影响整个进程的界面渲染属于较大的改动。5.4 中文路径和中文标题本地好好的换机就乱现象本地跑通拷到另一台机器上FileExists对所有中文路径返回 False。原因脚本文件编码和目标机器的系统区域设置不一致。UTF-8 无 BOM 的脚本里写中文常量解析器按 ANSI 读字节序列就变了。中文版 Windows 和其它语言版本的默认代码页不同问题只在跨机器时暴露。解决脚本统一保存为 ANSIGBK或带 BOM 的 UTF-8路径一律用ScriptDir拼接不在代码里硬编码中文目录名。交付前在目标语言环境的机器上跑一次冒烟测试这一步别省。5.5 编译产物第一次运行特别慢或者直接被拦现象双击 exe 后要等三五秒才有反应或者干脆被安全软件静默隔离什么提示都没有。原因/comp 4的产物需要先解压自身体积首次运行还有系统的文件扫描开销被隔离则是因为打包特征触发了启发式规则。解决启动慢的话把压缩级别降到 2 或 3用体积换启动速度被隔离就走白名单流程别反复改代码试图绕过。另外编译后第一次运行前先确认杀软日志很多时候你以为的「脚本有 bug」实际是文件已经不在了。6. 把 WinWait 换成带重试的等待函数一次改完后面都省心WinWait的超时值是固定的网络慢一点、机器卡一点就超时然后把整个流程带偏。我在一个批量部署脚本上吃过大亏单机测试 3 秒能出来的窗口在批量机器上因为同时跑着杀毒扫描15 秒才出来脚本早就放弃退出了。后来统一改成「短超时 多次重试 全程落日志」的写法这类问题再没出现过。; 带重试的等待窗口返回句柄失败返回 0 Func WaitWindow($sTitle, $iTimeout 5, $iRetry 6, $iInterval 1000) For $i 1 To $iRetry Local $h WinWait($sTitle, , $iTimeout) If $h 0 Then LogWrite(第 $i 次尝试命中窗口 $sTitle) Return $h EndIf LogWrite(第 $i 次等待超时休眠 $iInterval ms 重试) Sleep($iInterval) Next LogWrite(重试 $iRetry 次仍未等到 $sTitle) Return 0 EndFunc Func LogWrite($sMsg) Local $sLine YEAR - MON - MDAY HOUR : MIN : SEC $sMsg ConsoleWrite($sLine CRLF) FileWriteLine(ScriptDir \run.log, $sLine) EndFunc ; 调用方只需要判断一次 Local $hMain WaitWindow([CLASS:Notepad], 5, 6, 1000) If $hMain 0 Then MsgBox(16, 失败, 主窗口未出现详见 run.log) Exit 1 EndIf这里的取舍是单次WinWait给短超时5 秒外层套 6 次重试两次之间休眠 1 秒最坏情况总等待 36 秒最好的情况 1 秒内返回。相比直接把超时设成 60 秒好处是每次失败都有日志能看出到底是「一直没出现」还是「出现了但标题不匹配」——前者是环境问题后者是匹配规则问题排查方向完全不同。Sleep的间隔不要设太短窗口创建本身需要时间100ms 级别的轮询只是白白占 CPU。日志函数里我特意同时写控制台和文件调试期看控制台交付后看文件ScriptDir保证日志跟着 exe 走不会写到系统目录里找不到。这个习惯是从一次客户现场事故之后养成的那次脚本卡在第三步没有任何输出我只能远程连上去一步步手工重放花了两个小时才定位到一个弹窗被安全软件换成了自家样式。从那以后我每次交付前都强制跑一遍带日志的版本确认每一行时序都对得上才敢打包。希望帮到你。本文还有配套的精品资源点击获取