Write ffmpeg dir to user PATH via registry instead of setx

setx truncates values at 1024 characters, and the old code fed it the
merged process PATH (system + user), permanently duplicating every
system entry into the user hive and silently dropping anything past the
limit. Read and rewrite only the HKCU Environment Path value with
winreg, preserving REG_EXPAND_SZ, and broadcast WM_SETTINGCHANGE.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jaroslav Beneš
2026-07-25 01:23:04 +02:00
parent 202dd9eaee
commit b40deb0d5f
+26 -20
View File
@@ -337,29 +337,35 @@ def install_ffmpeg_windows(progress_callback=None) -> bool:
if progress_callback: if progress_callback:
progress_callback("🔧 Configuring system paths...") progress_callback("🔧 Configuring system paths...")
# Add to System Path # Persist to the user PATH via the registry. setx must not be used here:
user_path = os.environ.get("PATH", "") # it truncates values at 1024 characters, and os.environ["PATH"] is the
path_parts = user_path.split(os.pathsep) # merged system+user PATH, so writing it back would permanently duplicate
# every system entry into the user hive.
# Remove old FFmpeg paths and add new one
cleaned_paths = [p for p in path_parts if "ffmpeg" not in p.lower() or str(bin_dir) in p]
if str(bin_dir) not in cleaned_paths:
cleaned_paths.insert(0, str(bin_dir))
new_path = os.pathsep.join(cleaned_paths)
try: try:
subprocess.run( import winreg
["setx", "PATH", new_path],
creationflags=SUBPROCESS_CREATIONFLAGS, with winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Environment", 0, winreg.KEY_READ | winreg.KEY_WRITE) as key:
timeout=30, try:
check=True, stored_path, value_type = winreg.QueryValueEx(key, "Path")
) except FileNotFoundError:
os.environ["PATH"] = new_path stored_path, value_type = "", winreg.REG_EXPAND_SZ
user_parts = [p for p in stored_path.split(os.pathsep) if p]
# Drop stale ffmpeg entries we previously added, then prepend the new one
user_parts = [p for p in user_parts if "ffmpeg" not in p.lower() or p == str(bin_dir)]
if str(bin_dir) not in user_parts:
user_parts.insert(0, str(bin_dir))
winreg.SetValueEx(key, "Path", 0, value_type, os.pathsep.join(user_parts))
# Broadcast the change so new shells pick it up without relogin
import ctypes
ctypes.windll.user32.SendMessageTimeoutW(0xFFFF, 0x001A, 0, "Environment", 0x0002, 5000, None)
except Exception as e: except Exception as e:
logger.warning(f"Failed to update PATH permanently: {e}") logger.warning(f"Failed to update PATH permanently: {e}")
# Still update for current session
os.environ["PATH"] = new_path # Update for the current session regardless
if str(bin_dir) not in os.environ.get("PATH", "").split(os.pathsep):
os.environ["PATH"] = str(bin_dir) + os.pathsep + os.environ.get("PATH", "")
# Verify installation # Verify installation
if progress_callback: if progress_callback: