feat: 全面优化用户界面和操作流程 1.统一所有弹窗界面风格 2.优化禁用更新/突破限制/刷新授权的操作流程 3.增加复制命令按钮功能 4.改进错误提示和操作指引 5.提升整体操作流畅度
This commit is contained in:
@@ -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账号激活成功!")
|
||||
|
||||
Reference in New Issue
Block a user