import os import subprocess import time import logging import sys import getpass APP_NAME = "sening_vdp" LOG_FILE = "sening_vdp.log" BASE_DIR = os.path.abspath(os.path.dirname(sys.executable)) logging.basicConfig( filename=os.path.join(BASE_DIR, LOG_FILE), level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s' ) def start_process(name, exe_path, args, log_file): try: full_path = os.path.abspath(exe_path) logging.info(f"Starting {name}: {full_path} {' '.join(args)}") # 打开日志文件,追加写入 log_fh = open(log_file, "a", encoding="utf-8") # CREATE_NO_WINDOW 隐藏窗口 CREATE_NO_WINDOW = 0x08000000 process = subprocess.Popen( [full_path] + args, cwd=os.path.dirname(full_path), stdout=log_fh, stderr=subprocess.STDOUT, creationflags=CREATE_NO_WINDOW, universal_newlines=True ) return process except Exception as e: logging.error(f"Failed to start {name}: {e}") return None def start_process_with_retry(name, exe_path, args, log_file, retry_interval=120): full_path = os.path.abspath(exe_path) CREATE_NO_WINDOW = 0x08000000 while True: try: logging.info(f"[{name}] 尝试启动:{full_path} {' '.join(args)}") process = subprocess.Popen( [full_path] + args, cwd=os.path.dirname(full_path), stdout=subprocess.PIPE, stderr=subprocess.STDOUT, creationflags=CREATE_NO_WINDOW, universal_newlines=True, encoding="utf-8", ) success = False while True: line = process.stdout.readline() print(line) if not line: break logging.info(f"[{name}] {line.strip()}") if "connect to server error" in line or "login to the server failed" in line: logging.warning(f"[{name}] 连接失败,{retry_interval} 秒后重试...") process.kill() time.sleep(retry_interval) break if "start proxy success" in line : success = True if success: logging.info(f"[{name}] 成功启动并连接") return process except Exception as e: logging.error(f"[{name}] 启动异常:{e}") time.sleep(retry_interval) def add_to_startup(): try: # 获取当前用户名和路径 user = getpass.getuser() startup_folder = fr"C:\Users\{user}\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup" # 当前可执行文件路径 exe_path = os.path.join(BASE_DIR,"sening_vdp.exe") shortcut_path = os.path.join(startup_folder, "sening_vdp.lnk") # 创建快捷方式 import pythoncom from win32com.shell import shell, shellcon from win32com.client import Dispatch shell = Dispatch('WScript.Shell') shortcut = shell.CreateShortcut(shortcut_path) shortcut.TargetPath = exe_path shortcut.WorkingDirectory = os.path.dirname(exe_path) shortcut.IconLocation = exe_path shortcut.Save() except Exception as e: print(f"e") pass if __name__ == "__main__": logging.info("程序启动") add_to_startup() import sys import win32event import win32api import winerror mutex = win32event.CreateMutex(None, False, "Global\\SeningVDPOnlyOne") last_error = win32api.GetLastError() if last_error == winerror.ERROR_ALREADY_EXISTS: # 已经运行过了,退出 sys.exit(0) # 启动 Clash(当前目录下 clash.exe,配置文件 clash.yaml) clash_process = start_process("sening_vdp1", "sening_vdp1.exe", ["-f", "sening_vdp1.yaml"], LOG_FILE) time.sleep(2) # 启动 frpc(当前目录下 frpc.exe,配置文件 frpc.toml) frpc_process = start_process_with_retry("sening_vdp2", "sening_vdp2.exe", ["-c", "sening_vdp2.toml"], LOG_FILE) try: if clash_process: clash_process.wait() if frpc_process: frpc_process.wait() except KeyboardInterrupt: logging.info("程序被中断,退出")