Windows 本地程序执行脚本踩坑记录:MySQL 初始化失败,最后发现竟然是“找错了数据库”

📅 2026/7/10 3:32:41 👁️ 阅读次数 📝 编程学习
Windows 本地程序执行脚本踩坑记录:MySQL 初始化失败,最后发现竟然是“找错了数据库”

最近在做一个 Windows 本地部署的软件激活功能时,遇到了一个非常“隐蔽”的问题。

功能本身其实不复杂:

  • 用户激活程序
  • 程序执行 .bat 脚本
  • 自动初始化数据库
  • 导入 SQL 文件

结果现场一直初始化失败,而且最离谱的是:有时候能成功,有时候失败,同样的安装包,在不同电脑表现还不一样

一开始真的挺懵的。后来一路排查,才发现问题根本不是 SQL,也不是权限,而是:脚本连错 MySQL 了。

@echo off
echo [INFO] 脚本启动中...
SETLOCAL ENABLEDELAYEDEXPANSION
set purchasePackage=%~1
if "%purchasePackage%"=="" (echo [ERROR] 未指定 SQL 文件名exit /b 1
)echo [INFO] 目标 SQL 文件:%purchasePackage%
echo [INFO] 正在从注册表读取安装路径...
for /f "tokens=1,2,*" %%i in ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Ericsson\***\Install" /v InstallPath ^| find /i "InstallPath"') do set "regvalue=%%k"
if not defined regvalue (echo [ERROR] 无法从注册表获取安装路径exit /b 1
)echo [INFO] 安装路径:%regvalue%
set "pid="
set "port="
for /f "tokens=2 delims=:" %%a in ('sc queryex "mysql" ^| findstr /i "pid"') do set "pid=%%a"
for /f "tokens=2" %%i in ('netstat -ano ^| findstr %pid%') do (set port=%%ibreak;
)
set port=%port:~-4,4%
echo [INFO] 找到 MySQL 进程 PID: %pid%
echo [INFO] 识别到的 MySQL 端口: %port%
cd /d %~dp0
cd %regvalue%\***\E***mysql\mysql\binset "log_dir=D:\***_Logs"
if not exist "%log_dir%" mkdir "%log_dir%"
set "temp_log=%log_dir%\mysql_import_%date:~0,4%%date:~5,2%%date:~8,2%_%time:~0,2%%time:~3,2%.log"echo [INFO] 开始执行数据库导入操作...
".\mysql.exe" -uroot -proot -P%port% -D main < "%regvalue%\E***\E***\sql\%purchasePackage%" > "%temp_log%" 2>&1
set "mysql_exit_code=%errorlevel%"echo [INFO] 执行完数据库导入操作...
cd /d %~dp0
cd %regvalue%\E***\E****_mysql\sql
if "%mysql_exit_code%"=="0" (echo [SUCCESS] 数据库导入成功del %purchasePackage%exit /b 0
) else (echo [FAIL] 数据库导入失败,退出码:%mysql_exit_code%type "%temp_log%"exit /b %mysql_exit_code%
)

这是一个 Windows 本地部署程序。

激活时会执行一个批处理脚本,大概流程:

  1. 从注册表读取软件安装目录
  2. 找到 MySQL 安装路径
  3. 获取 MySQL 运行端口
  4. 调用 mysql.exe
  5. 执行 SQL 初始化数据

核心执行语句类似这样:

".\mysql.exe" -uroot -proot -P%port% -D main < xxx.sql

逻辑看起来完全没问题。

但现场就是会失败。

增加日志打印有时候由于编码问题,端口号一开始没打印出来,还是在乱猜,后面重新看才注意到的,所以写脚本还是要把日志打印齐全一点,不然排查起来麻烦:

echo [INFO] 找到 MySQL 进程 PID: %pid%
echo [INFO] 识别到的 MySQL 端口: %port%

结果终于发现异常。

最开始我的脚本是这样获取 MySQL 进程的:

tasklist | findstr mysql

Windows 电脑里可能有很多 MySQL:

  • MySQL 5.7
  • MySQL 8
  • Navicat 自带
  • WAMP
  • XAMPP
  • 开发环境数据库

而:

tasklist 只能告诉你:
当前有哪些 mysql.exe

但它并不知道:哪个才是你程序自己的 MySQL

于是:脚本随机取到了别人的 MySQL。

最终导致:端口不对,数据库不存在,初始化失败

后来改成了:

sc queryex "mysql"

通过:

Windows 服务名

精准获取对应服务的 PID。

代码:

for /f "tokens=2 delims=:" %%a in ('sc queryex "mysql" ^| findstr /i "pid"') do set "pid=%%a"

然后再通过:

netstat -ano

获取对应 PID 的端口。

这样就不会串了。

因为:

服务名 -> PID -> 端口

是一条精准链路。

而不是:

mysql.exe -> 随便找一个

为什么这个方案更可靠,因为 Windows 上:进程名可能重复但服务名通常唯一

例如:

mysql
mysqld
MySQL80
MariaDB

都可能存在。

所以:通过服务名找 PID,才是更稳定的方式。

给做 Windows 本地部署程序的一些建议

一定要打印日志不要怕日志多

不要通过进程名定位服务优先:服务名 -> PID -> 端口

不要:tasklist 找 mysql.exe

一定考虑用户电脑已有环境用户电脑可能已经有:

  • Java
  • Redis
  • MySQL
  • Python
  • Nginx

你的程序不一定是唯一的。路径一定加引号Windows 批处理里:"%path%"几乎是必须的。