feat: 全面优化用户界面和操作流程 1.统一所有弹窗界面风格 2.优化禁用更新/突破限制/刷新授权的操作流程 3.增加复制命令按钮功能 4.改进错误提示和操作指引 5.提升整体操作流畅度

This commit is contained in:
huangzhenpc
2025-02-14 20:44:16 +08:00
parent 26e159d71c
commit ae698796e7
9 changed files with 945 additions and 509 deletions

View File

@@ -352,106 +352,30 @@ class AccountSwitcher:
return "网络请求失败,请稍后重试"
return str(error)
def get_process_details(self, process_name: str) -> List[Dict]:
"""获取进程详细信息
Args:
process_name: 进程名称
Returns:
List[Dict]: 进程详细信息列表
"""
try:
# 使用 tasklist 命令替代 wmi
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
output = subprocess.check_output(
f'tasklist /FI "IMAGENAME eq {process_name}" /FO CSV /NH',
startupinfo=startupinfo,
shell=True
).decode('gbk')
processes = []
if output.strip():
for line in output.strip().split('\n'):
if line.strip():
parts = line.strip('"').split('","')
if len(parts) >= 2:
processes.append({
'name': parts[0],
'pid': parts[1]
})
return processes
except Exception as e:
logging.error(f"获取进程信息失败: {str(e)}")
return []
def close_cursor_process(self) -> bool:
"""关闭所有Cursor进程
Returns:
bool: 是否成功关闭所有进程
"""
"""关闭所有Cursor相关进程"""
try:
if sys.platform == "win32":
# 创建startupinfo对象来隐藏命令行窗口
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
startupinfo.wShowWindow = subprocess.SW_HIDE
# 获取进程详情
processes = self.get_process_details("Cursor.exe")
if processes:
logging.info(f"发现 {len(processes)} 个Cursor进程")
for p in processes:
logging.info(f"进程信息: PID={p['pid']}, 路径={p['name']}")
# 直接使用taskkill命令强制结束所有相关进程
process_names = ["Cursor.exe", "devsense.php.ls.exe", "intelliphp.ls.exe"]
for name in process_names:
try:
subprocess.run(
f"taskkill /f /t /im {name} >nul 2>&1",
startupinfo=startupinfo,
shell=True,
timeout=5
)
except:
pass
# 尝试关闭进程
subprocess.run(
"taskkill /f /im Cursor.exe >nul 2>&1",
startupinfo=startupinfo,
shell=True
)
# 等待进程关闭,增加重试次数和等待时间
retry_count = 0
max_retries = 10 # 增加最大重试次数
wait_time = 2 # 增加每次等待时间
while retry_count < max_retries:
remaining_processes = self.get_process_details("Cursor.exe")
if not remaining_processes:
logging.info("所有Cursor进程已关闭")
# 额外等待一段时间确保系统资源完全释放
time.sleep(2)
return True
retry_count += 1
if retry_count >= max_retries:
processes = self.get_process_details("Cursor.exe")
if processes:
logging.error(f"无法关闭以下进程:")
for p in processes:
logging.error(f"PID={p['pid']}, 路径={p['name']}")
# 最后一次尝试强制结束
try:
subprocess.run(
"taskkill /f /im Cursor.exe /t >nul 2>&1",
startupinfo=startupinfo,
shell=True
)
time.sleep(2)
except:
pass
return False
logging.warning(f"等待进程关闭, 尝试 {retry_count}/{max_retries}...")
time.sleep(wait_time)
# 等待一小段时间确保进程完全关闭
time.sleep(2)
return True
else:
# 其他系统的处理
if sys.platform == "darwin":
subprocess.run("killall Cursor 2>/dev/null", shell=True)
else:
@@ -472,12 +396,11 @@ class AccountSwitcher:
return False
# 2. 使用新的重置工具类执行重置
success, message = self.resetter.reset_cursor(disable_update=True)
success, message = self.resetter.reset_cursor(disable_update=False) # 不在这里禁用更新
if not success:
logging.error(f"重置失败: {message}")
return False
# 不在这里重启Cursor让调用者决定何时重启
logging.info("机器码重置完成")
return True
@@ -486,104 +409,55 @@ class AccountSwitcher:
return False
def restart_cursor(self) -> bool:
"""重启Cursor编辑器
Returns:
bool: 是否成功重启
"""
"""重启Cursor编辑器"""
try:
logging.info("正在重启Cursor...")
# 1. 确保进程已关闭
self.close_cursor_process()
# 确保进程已关闭
if not self.close_cursor_process():
logging.error("无法关闭Cursor进程")
return False
# 等待系统资源释放
time.sleep(3)
# 2. 等待一小段时间
time.sleep(2)
# 启动Cursor
# 3. 启动Cursor
if sys.platform == "win32":
cursor_exe = self.cursor_path / "Cursor.exe"
if cursor_exe.exists():
max_retries = 3
for attempt in range(max_retries):
try:
# 使用subprocess启动
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
try:
# 使用ShellExecuteW以管理员权限启动
result = ctypes.windll.shell32.ShellExecuteW(
None, # 父窗口句柄
"runas", # 以管理员权限运行
str(cursor_exe), # 程序路径
None, # 参数
str(cursor_exe.parent), # 工作目录
1 # 正常窗口显示
)
# ShellExecuteW返回值大于32表示成功
if result > 32:
time.sleep(3) # 等待启动
return True
else:
logging.error(f"启动Cursor失败错误码: {result}")
return False
subprocess.Popen(
str(cursor_exe),
startupinfo=startupinfo,
creationflags=subprocess.CREATE_NEW_CONSOLE
)
# 等待进程启动
time.sleep(5) # 增加等待时间
# 验证进程是否启动
processes = self.get_process_details("Cursor.exe")
if processes:
logging.info("Cursor启动成功")
return True
else:
if attempt < max_retries - 1:
logging.warning(f"启动尝试 {attempt + 1} 失败,准备重试...")
time.sleep(3)
continue
logging.error("Cursor进程未找到")
# 尝试使用 os.startfile 作为备选方案
try:
os.startfile(str(cursor_exe))
time.sleep(5)
logging.info("使用备选方案启动Cursor")
return True
except Exception as e:
logging.error(f"备选启动方案失败: {str(e)}")
return False
except Exception as e:
if attempt < max_retries - 1:
logging.warning(f"启动尝试 {attempt + 1} 失败: {str(e)},准备重试...")
time.sleep(3)
continue
logging.error(f"启动Cursor失败: {str(e)}")
# 尝试使用 os.startfile 作为最后的备选方案
try:
os.startfile(str(cursor_exe))
time.sleep(5)
logging.info("使用备选方案启动Cursor")
return True
except Exception as e:
logging.error(f"备选启动方案失败: {str(e)}")
return False
except Exception as e:
logging.error(f"启动Cursor失败: {str(e)}")
return False
else:
logging.error(f"未找到Cursor程序: {cursor_exe}")
return False
elif sys.platform == "darwin":
else:
try:
subprocess.run("open -a Cursor", shell=True, check=True)
time.sleep(5)
logging.info("Cursor启动成功")
if sys.platform == "darwin":
subprocess.run("open -a Cursor", shell=True, check=True)
else:
subprocess.run("sudo cursor &", shell=True, check=True)
time.sleep(3)
return True
except subprocess.CalledProcessError as e:
logging.error(f"启动Cursor失败: {str(e)}")
return False
elif sys.platform == "linux":
try:
subprocess.run("cursor &", shell=True, check=True)
time.sleep(5)
logging.info("Cursor启动成功")
return True
except subprocess.CalledProcessError as e:
except Exception as e:
logging.error(f"启动Cursor失败: {str(e)}")
return False
return False
except Exception as e:
logging.error(f"重启Cursor失败: {str(e)}")
return False
@@ -776,12 +650,14 @@ class AccountSwitcher:
if not self.reset_machine_id():
return False, "重置机器码失败"
# 7. 重启Cursor(只在这里执行一次重启)
# 7. 重启Cursor
logging.info("正在重启Cursor...")
retry_count = 0
max_retries = 3
while retry_count < max_retries:
if self.restart_cursor():
# 等待进程完全启动
time.sleep(5)
break
retry_count += 1
if retry_count < max_retries:
@@ -824,50 +700,17 @@ class AccountSwitcher:
"""禁用Cursor更新"""
try:
# 1. 先关闭所有Cursor进程
if sys.platform == "win32":
# 创建startupinfo对象来隐藏命令行窗口
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
startupinfo.wShowWindow = subprocess.SW_HIDE
# 关闭Cursor
subprocess.run(
"taskkill /f /im Cursor.exe >nul 2>&1",
startupinfo=startupinfo,
shell=True
)
time.sleep(2)
if not self.close_cursor_process():
return False, "无法关闭Cursor进程请手动关闭后重试"
# 2. 删除updater目录并创建同名文件以阻止更新
updater_path = Path(os.getenv('LOCALAPPDATA')) / "cursor-updater"
# 2. 调用resetter的disable_auto_update方法
success, message = self.resetter.disable_auto_update()
if not success:
logging.error(f"禁用自动更新失败: {message}")
return False, f"禁用更新失败: {message}"
try:
# 如果是目录,则删除
if updater_path.is_dir():
import shutil
shutil.rmtree(str(updater_path))
logging.info("删除updater目录成功")
# 如果是文件,则删除
if updater_path.is_file():
os.remove(str(updater_path))
logging.info("删除updater文件成功")
# 创建同名空文件
updater_path.touch()
logging.info("创建updater空文件成功")
# 3. 重启Cursor
cursor_exe = self.cursor_path / "Cursor.exe"
if cursor_exe.exists():
os.startfile(str(cursor_exe))
logging.info("Cursor重启成功")
return True, "Cursor更新已禁用程序已重启"
except Exception as e:
logging.error(f"操作updater文件失败: {str(e)}")
return False, f"禁用更新失败: {str(e)}"
logging.info("更新已禁用")
return True, "Cursor更新已禁用"
except Exception as e:
logging.error(f"禁用Cursor更新失败: {str(e)}")
@@ -967,6 +810,26 @@ class AccountSwitcher:
return False, "多次尝试后心跳发送失败"
def bypass_cursor_limit(self) -> Tuple[bool, str]:
"""突破Cursor使用限制"""
try:
# 1. 先关闭所有Cursor进程
if not self.close_cursor_process():
return False, "无法关闭Cursor进程请手动关闭后重试"
# 2. 调用resetter的reset_cursor方法
success, message = self.resetter.reset_cursor(disable_update=True)
if not success:
logging.error(f"突破限制失败: {message}")
return False, f"突破限制失败: {message}"
logging.info("突破限制成功")
return True, "突破限制成功"
except Exception as e:
logging.error(f"突破限制失败: {str(e)}")
return False, f"突破限制失败: {str(e)}"
def main():
"""主函数"""
try:
@@ -982,13 +845,15 @@ def main():
switcher = AccountSwitcher()
print("\n=== Cursor账号切换工具 ===")
print("1. 激活并切换账号")
print("2. 仅重置机器码")
print("1. 禁用自动更新")
print("2. 突破使用限制")
print("3. 激活并切换账号")
print("4. 仅重置机器码")
while True:
try:
choice = int(input("\n请选择操作 (1 或 2): ").strip())
if choice in [1, 2]:
choice = int(input("\n请选择操作 (1-4): ").strip())
if choice in [1, 2, 3, 4]:
break
else:
print("无效的选项,请重新输入")
@@ -996,6 +861,18 @@ def main():
print("请输入有效的数字")
if choice == 1:
success, message = switcher.disable_cursor_update()
if success:
print("\n更新已禁用!")
else:
print(f"\n禁用更新失败: {message}")
elif choice == 2:
success, message = switcher.bypass_cursor_limit()
if success:
print("\n突破限制成功!")
else:
print(f"\n突破限制失败: {message}")
elif choice == 3:
activation_code = input("请输入激活码: ").strip()
if switcher.activate_and_switch(activation_code):
print("\n账号激活成功!")