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:
chrome-storm-c442
2026-03-02 02:11:02 -05:00
parent acc93f98e3
commit 1218f4d72d
3 changed files with 59 additions and 31 deletions

View File

@@ -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

Binary file not shown.

View File

@@ -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"