diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0c3116b..1fab251 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -87,6 +87,14 @@ jobs: - name: Build exe run: python build_windows.py + - name: Unblock files (rimuovi MOTW pre-zip) + shell: pwsh + run: | + # Per ridurre l'incidenza del bug "Failed to resolve + # Python.Runtime.Loader.Initialize" causato da Mark of the Web. + Get-ChildItem -Path dist/MusicTools -Recurse -Include *.dll,*.exe,*.pyd ` + | Unblock-File + - name: Package -> zip shell: pwsh run: | diff --git a/core/config.py b/core/config.py index 4548bf1..2a51184 100644 --- a/core/config.py +++ b/core/config.py @@ -5,7 +5,7 @@ import os import sys from pathlib import Path -VERSION = "v1.7.6" +VERSION = "v1.7.7" APP_NAME = "MusicTools" diff --git a/main.py b/main.py index f7d21cb..5af6b11 100644 --- a/main.py +++ b/main.py @@ -11,20 +11,37 @@ from pathlib import Path # senza l'inizializzazione esplicita. Fix conferma: # https://github.com/pythonnet/pythonnet/issues/2178 if sys.platform == "win32": - try: - # Punta pythonnet ai propri file runtime dentro al bundle PyInstaller. - if getattr(sys, "frozen", False): + # ============================================================ + # Fix Windows: rimuovi Mark of the Web (MOTW) dalle DLL bundled. + # Quando l'utente scarica il .zip dal browser, Windows aggiunge + # uno stream NTFS Zone.Identifier a TUTTI i file estratti. + # .NET Framework 4.x rifiuta silenziosamente di risolvere i + # symbol export degli assembly managed con MOTW -> il loader + # netfx di pythonnet fallisce con "Failed to resolve + # Python.Runtime.Loader.Initialize". + # Soluzione: cancelliamo lo stream :Zone.Identifier da ogni + # .dll/.exe del bundle al primo avvio (operazione idempotente + # e sicura: l'utente ha gia eseguito l'exe esplicitamente). + # Vedi: https://github.com/r0x0r/pywebview/issues/1215 + # ============================================================ + if getattr(sys, "frozen", False): + try: + import ctypes + _kernel32 = ctypes.windll.kernel32 _bundle = Path(sys._MEIPASS) # type: ignore[attr-defined] - _rt = _bundle / "pythonnet" / "runtime" - if _rt.exists(): - os.environ["PYTHONNET_RUNTIME"] = "netfx" - os.environ["PYTHONNET_PYDLL"] = sys.executable + for _f in _bundle.rglob("*"): + if _f.suffix.lower() in (".dll", ".exe", ".pyd"): + _kernel32.DeleteFileW(f"{_f}:Zone.Identifier") + except Exception as _e: + print(f"[bootstrap] MOTW cleanup failed: {_e}") + + try: + if getattr(sys, "frozen", False): + os.environ["PYTHONNET_RUNTIME"] = "netfx" from pythonnet import load as _pythonnet_load _pythonnet_load("netfx") import clr # noqa: F401 - inizializza il loader except Exception as _e: - # Se il preload fallisce, lasciamo che webview tenti comunque: - # l'errore originale verra' mostrato con stack trace. print(f"[bootstrap] preload pythonnet failed: {_e}") import webview diff --git a/requirements.txt b/requirements.txt index 41a9779..0fd41eb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,4 +5,5 @@ mutagen>=1.47.0 pyobjc-core>=10.0 ; sys_platform == "darwin" pyobjc-framework-Cocoa>=10.0 ; sys_platform == "darwin" pyobjc-framework-WebKit>=10.0 ; sys_platform == "darwin" -pythonnet==3.0.3 ; sys_platform == "win32" +pythonnet==3.0.5 ; sys_platform == "win32" +clr-loader==0.2.7.post0 ; sys_platform == "win32"