v1.8.89: fix DLL error on auto-update — clean all stale _MEI dirs, launch via explorer.exe
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -262,47 +262,75 @@ class UpdateChecker:
|
|||||||
return self._apply_linux(binary_path, current_exe)
|
return self._apply_linux(binary_path, current_exe)
|
||||||
|
|
||||||
def _apply_windows(self, new_exe: str, current_exe: str) -> bool:
|
def _apply_windows(self, new_exe: str, current_exe: str) -> bool:
|
||||||
"""Windows update: create hidden .vbs that runs .bat silently."""
|
"""Windows update: PowerShell script waits for exit, copies, launches."""
|
||||||
try:
|
try:
|
||||||
tmp_dir = tempfile.gettempdir()
|
tmp_dir = tempfile.gettempdir()
|
||||||
bat_path = os.path.join(tmp_dir, "sm_update.bat")
|
ps_path = os.path.join(tmp_dir, "sm_update.ps1")
|
||||||
vbs_path = os.path.join(tmp_dir, "sm_update.vbs")
|
vbs_path = os.path.join(tmp_dir, "sm_update.vbs")
|
||||||
pid = os.getpid()
|
pid = os.getpid()
|
||||||
|
|
||||||
# Clean up old PyInstaller _MEI dirs to avoid DLL conflicts
|
|
||||||
mei_dir = getattr(sys, '_MEIPASS', '')
|
mei_dir = getattr(sys, '_MEIPASS', '')
|
||||||
|
exe_dir = os.path.dirname(current_exe)
|
||||||
|
|
||||||
bat_content = f"""@echo off
|
ps_content = f"""
|
||||||
:wait
|
$ErrorActionPreference = 'Stop'
|
||||||
tasklist /fi "PID eq {pid}" 2>NUL | find "{pid}" >NUL
|
$pid = {pid}
|
||||||
if %ERRORLEVEL% == 0 (
|
$src = '{new_exe}'
|
||||||
timeout /t 1 /nobreak >NUL
|
$dst = '{current_exe}'
|
||||||
goto wait
|
$mei = '{mei_dir}'
|
||||||
)
|
$exeDir = '{exe_dir}'
|
||||||
timeout /t 2 /nobreak >NUL
|
$tempDir = '{tmp_dir}'
|
||||||
if exist "{mei_dir}" rmdir /s /q "{mei_dir}" >NUL 2>NUL
|
|
||||||
copy /Y "{new_exe}" "{current_exe}" >NUL
|
# Wait for old process to exit
|
||||||
if %ERRORLEVEL% NEQ 0 (
|
while (Get-Process -Id $pid -ErrorAction SilentlyContinue) {{
|
||||||
timeout /t 3 /nobreak >NUL
|
Start-Sleep -Seconds 1
|
||||||
copy /Y "{new_exe}" "{current_exe}" >NUL
|
}}
|
||||||
if %ERRORLEVEL% NEQ 0 exit /b 1
|
Start-Sleep -Seconds 2
|
||||||
)
|
|
||||||
timeout /t 2 /nobreak >NUL
|
# Clean ALL stale _MEI directories (PyInstaller temp dirs)
|
||||||
start "" "{current_exe}"
|
Get-ChildItem -Path $tempDir -Directory -Filter '_MEI*' -ErrorAction SilentlyContinue | ForEach-Object {{
|
||||||
del "{new_exe}" >NUL 2>NUL
|
Remove-Item -Path $_.FullName -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
del "{bat_path}"
|
}}
|
||||||
del "%~f0"
|
Start-Sleep -Seconds 1
|
||||||
|
|
||||||
|
# Copy with retry
|
||||||
|
$copied = $false
|
||||||
|
for ($i = 0; $i -lt 5; $i++) {{
|
||||||
|
try {{
|
||||||
|
Copy-Item -Path $src -Destination $dst -Force
|
||||||
|
$srcSize = (Get-Item $src).Length
|
||||||
|
$dstSize = (Get-Item $dst).Length
|
||||||
|
if ($srcSize -eq $dstSize) {{
|
||||||
|
$copied = $true
|
||||||
|
break
|
||||||
|
}}
|
||||||
|
}} catch {{}}
|
||||||
|
Start-Sleep -Seconds 2
|
||||||
|
}}
|
||||||
|
|
||||||
|
if (-not $copied) {{ exit 1 }}
|
||||||
|
|
||||||
|
Start-Sleep -Seconds 2
|
||||||
|
|
||||||
|
# Launch new exe via explorer.exe (mimics user double-click, clean environment)
|
||||||
|
Start-Process explorer.exe $dst
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
Start-Sleep -Seconds 3
|
||||||
|
Remove-Item -Path $src -Force -ErrorAction SilentlyContinue
|
||||||
|
Remove-Item -Path '{ps_path}' -Force -ErrorAction SilentlyContinue
|
||||||
"""
|
"""
|
||||||
with open(bat_path, "w") as f:
|
with open(ps_path, "w", encoding="utf-8") as f:
|
||||||
f.write(bat_content)
|
f.write(ps_content)
|
||||||
|
|
||||||
# VBS wrapper runs .bat completely hidden (no CMD flash)
|
# VBS wrapper launches PowerShell hidden (no window flash)
|
||||||
vbs_content = f'CreateObject("Wscript.Shell").Run """{bat_path}""", 0, False\n'
|
vbs_content = (
|
||||||
|
'CreateObject("Wscript.Shell").Run '
|
||||||
|
'"powershell -ExecutionPolicy Bypass -WindowStyle Hidden '
|
||||||
|
f'-File ""{ps_path}""""", 0, False\n'
|
||||||
|
)
|
||||||
with open(vbs_path, "w") as f:
|
with open(vbs_path, "w") as f:
|
||||||
f.write(vbs_content)
|
f.write(vbs_content)
|
||||||
|
|
||||||
# Launch VBS via os.startfile — most reliable on Windows,
|
|
||||||
# works from frozen exe without PATH issues
|
|
||||||
os.startfile(vbs_path)
|
os.startfile(vbs_path)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|||||||
BIN
releases/ServerManager-v1.8.89-win-x64.exe
Normal file
BIN
releases/ServerManager-v1.8.89-win-x64.exe
Normal file
Binary file not shown.
@@ -1,6 +1,6 @@
|
|||||||
"""Version info for ServerManager."""
|
"""Version info for ServerManager."""
|
||||||
|
|
||||||
__version__ = "1.8.86"
|
__version__ = "1.8.89"
|
||||||
__app_name__ = "ServerManager"
|
__app_name__ = "ServerManager"
|
||||||
__author__ = "aibot777"
|
__author__ = "aibot777"
|
||||||
__description__ = "Desktop GUI for managing remote servers"
|
__description__ = "Desktop GUI for managing remote servers"
|
||||||
|
|||||||
Reference in New Issue
Block a user