@@ -210,12 +210,23 @@ Function .onInit
210210 ; used directly; NSIS will not pop a language picker because no picker
211211 ; macro is invoked here.
212212 ;
213- ; 升级安装前先把已注册的开机自启计划任务停掉——避免它在我们解压
214- ; embedded Python 时拉起 start-silent.bat → python.exe 持有
215- ; python313.dll 等文件,导致 tar 报 "Can't unlink already-existing
216- ; object" 整个安装失败。停掉后计划任务的定义还在,install 完成
217- ; 后用户可以重新启用"开机自启"组件(它会 register-task.ps1 重新注册)。
218- nsExec::ExecToLog ' schtasks /end /tn "QMT Gateway" >nul 2>&1 & exit 0'
213+ ; 升级安装前必须杀掉本应用持有的 python.exe 进程——否则后续 tar -xf
214+ ; 解压 python-embed.zip 会因为 .pyd/.dll 被进程持有而报
215+ ; "Can't unlink already-existing object" 并段错误退出(HEAP_CORRUPTION
216+ ; -1073740940)。
217+ ;
218+ ; 精确匹配:用 PowerShell + WMI 查询 CommandLine 含 "qmt_gateway" 或
219+ ; "quantide-gateway" 的 python.exe,**只杀这些**。不动用户的其它
220+ ; Python IDE / 脚本 / notebook / jupyter / venv 等。
221+ ; 计划任务 schtasks /end 也在并行做——避免它在我们 kill 后立刻重新拉
222+ ; 起 start-silent.bat → python.exe。停掉后计划任务定义还在,install
223+ ; 完成后用户可以重新启用"开机自启"组件(它会 register-task.ps1 重建)。
224+ ;
225+ ; PowerShell 逻辑放到独立 .ps1 文件里——NSIS -Command 内联复杂 PowerShell
226+ ; 会因为嵌套引号、CJK、$^ 转义等问题变得不可读且易错。
227+ InitPluginsDir
228+ File /oname= $PLUGINSDIR \kill-qmt-gateway-procs.ps1 " kill-qmt-gateway-procs.ps1"
229+ nsExec::ExecToLog ' cmd.exe /c schtasks /end /tn "QMT Gateway" >nul 2>&1 & powershell.exe -NoProfile -ExecutionPolicy Bypass -File "$PLUGINSDIR\kill-qmt-gateway-procs.ps1" >nul 2>&1 & exit 0'
219230FunctionEnd
220231
221232Function .onVerifyInstDir
@@ -250,13 +261,16 @@ Section "-Core" SEC_CORE
250261 ; 上一次 install 中途崩溃后可能留下半套残留文件(python.exe / .pyd / .dll
251262 ; 仍被进程持有,或被 TrustedInstaller / AV 接管所有者),NSIS 自带的
252263 ; RMDir /r 拿不动这些文件——结果后续 tar -xf 报 "Can't unlink
253- ; already-existing object" 整个安装中止。先用 takeown + icacls + cmd
254- ; rmdir 强制清掉 $INSTDIR\python 子目录(不能清整个 $INSTDIR,否则会
255- ; 把接下来要复制的 install-python.ps1 也一起干掉)。如果 cmd rmdir
256- ; 因为文件锁失败也没关系——后续 SetOverwrite on 会覆盖大部分文件,
257- ; 残留的旧文件不会阻塞 tar 解压(tar -xf 会报 warning 但失败的文件
258- ; 在下一轮重装时再清)。
259- nsExec::ExecToLog ' cmd.exe /c takeown /f "$INSTDIR\python" /a /r /d y >nul 2>&1 & icacls "$INSTDIR\python" /grant Administrators:F /t /c /q >nul 2>&1 & cd /d "%TEMP%" & rmdir /s /q "$INSTDIR\python" >nul 2>&1 & exit 0'
264+ ; already-existing object" 并以 STATUS_HEAP_CORRUPTION (-1073740940)
265+ ; 段错误退出,导致整个安装中止。先用 takeown + icacls + cmd rmdir 强
266+ ; 制清掉 $INSTDIR\python 子目录(不能清整个 $INSTDIR,否则会把接下
267+ ; 来要复制的 install-python.ps1 也一起干掉)。如果 cmd rmdir 因为文
268+ ; 件锁失败也没关系——后续 SetOverwrite on 会覆盖大部分文件,残留的
269+ ; 旧文件不会阻塞 tar 解压(tar -xf 会报 warning 但失败的文件在下一
270+ ; 轮重装时再清)。
271+ ;
272+ ; 重试 3 次:第一次可能因为某个文件刚被释放需要等 1s。
273+ nsExec::ExecToLog ' cmd.exe /c for /l %i in (1,1,3) do (takeown /f "$INSTDIR\python" /a /r /d y >nul 2>&1 & icacls "$INSTDIR\python" /grant Administrators:F /t /c /q >nul 2>&1 & cd /d "%TEMP%" & rmdir /s /q "$INSTDIR\python" >nul 2>&1 & if not exist "$INSTDIR\python" exit 0 & ping -n 2 127.0.0.1 >nul) & exit 0'
260274
261275 File /oname= ${INSTALLER_SCRIPT_NAME} " install-python.ps1"
262276 File " scrub-stale-installs.ps1"
0 commit comments