import os import sys import json import ctypes import logging import subprocess from pathlib import Path from datetime import datetime from typing import Optional, Tuple, Dict # 配置日志 logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s' ) def run_powershell_command(command: str) -> Tuple[bool, str]: """运行PowerShell命令 Args: command: PowerShell命令 Returns: Tuple[bool, str]: (是否成功, 输出或错误信息) """ try: # 创建完整的PowerShell命令 full_command = f'powershell.exe -Command "{command}"' # 运行命令 result = subprocess.run( full_command, capture_output=True, text=True, shell=True ) if result.returncode == 0: return True, result.stdout.strip() else: return False, result.stderr.strip() except Exception as e: return False, str(e) def is_admin(): """检查是否具有管理员权限""" try: return ctypes.windll.shell32.IsUserAnAdmin() except: return False def run_as_admin(): """以管理员权限重新运行程序""" try: if not is_admin(): # 获取当前脚本的路径 script = sys.argv[0] params = ' '.join(sys.argv[1:]) # 以管理员权限重新运行 ctypes.windll.shell32.ShellExecuteW( None, "runas", sys.executable, f'"{script}" {params}', None, 1 ) return True except Exception as e: logging.error(f"以管理员权限运行失败: {str(e)}") return False class CursorUpdateDisabler: """专门用于测试禁用Cursor更新的类""" def __init__(self): self.localappdata = os.getenv('LOCALAPPDATA') self.cursor_path = Path(self.localappdata) / "Programs" / "cursor" self.app_path = self.cursor_path / "resources" / "app" self.package_json = self.app_path / "package.json" self.updater_path = Path(self.localappdata) / "cursor-updater" def disable_auto_update(self) -> Tuple[bool, str]: """禁用自动更新 Returns: Tuple[bool, str]: (是否成功, 消息) """ try: logging.info(f"开始禁用更新操作...") logging.info(f"updater路径: {self.updater_path}") # 1. 使用PowerShell强制删除现有文件/目录 if self.updater_path.exists(): logging.info("发现现有updater文件/目录,尝试强制删除...") # 先获取完全控制权限 take_control_cmd = f'$path = "{self.updater_path}"; $acl = Get-Acl $path; $identity = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name; $fileSystemRights = [System.Security.AccessControl.FileSystemRights]::FullControl; $type = [System.Security.AccessControl.AccessControlType]::Allow; $rule = New-Object System.Security.AccessControl.FileSystemAccessRule($identity, $fileSystemRights, $type); $acl.SetAccessRule($rule); Set-Acl -Path $path -AclObject $acl' success, output = run_powershell_command(take_control_cmd) if not success: logging.warning(f"设置完全控制权限失败: {output}") # 强制删除 remove_cmd = f'Remove-Item -Path "{self.updater_path}" -Force -Recurse' success, output = run_powershell_command(remove_cmd) if not success: logging.error(f"强制删除失败: {output}") return False, f"删除现有文件失败: {output}" logging.info("成功删除现有文件/目录") # 2. 创建空文件 try: with open(self.updater_path, 'w') as f: pass logging.info("成功创建updater空文件") except Exception as e: logging.error(f"创建updater文件失败: {str(e)}") return False, f"创建updater文件失败: {str(e)}" # 3. 设置文件权限 try: # 设置文件为只读并禁止修改 protect_cmd = f'$path = "{self.updater_path}"; $acl = Get-Acl $path; $acl.SetAccessRuleProtection($true, $false); $identity = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name; $fileSystemRights = [System.Security.AccessControl.FileSystemRights]::Read; $type = [System.Security.AccessControl.AccessControlType]::Allow; $rule = New-Object System.Security.AccessControl.FileSystemAccessRule($identity, $fileSystemRights, $type); $acl.AddAccessRule($rule); Set-Acl -Path $path -AclObject $acl' success, output = run_powershell_command(protect_cmd) if not success: logging.error(f"设置文件权限失败: {output}") return False, f"设置文件权限失败: {output}" logging.info("成功设置文件权限") # 设置文件为只读 os.chmod(str(self.updater_path), 0o444) # 设置为只读 logging.info("成功设置文件只读属性") except Exception as e: logging.error(f"设置文件权限失败: {str(e)}") return False, f"设置文件权限失败: {str(e)}" # 4. 修改package.json try: if self.package_json.exists(): with open(self.package_json, "r", encoding="utf-8") as f: data = json.load(f) data["updateUrl"] = "" data["disableUpdate"] = True with open(self.package_json, "w", encoding="utf-8", newline='\n') as f: json.dump(data, f, indent=2) logging.info("成功修改package.json配置") except Exception as e: logging.warning(f"修改package.json失败: {str(e)}") # 5. 验证文件权限 try: if not self.updater_path.exists(): return False, "updater文件不存在" # 验证文件是否为只读 if os.access(str(self.updater_path), os.W_OK): logging.error("文件权限验证失败:文件可写") return False, "文件权限设置失败:文件仍然可写" logging.info("文件权限验证通过") except Exception as e: logging.error(f"验证文件权限失败: {str(e)}") return False, f"验证文件权限失败: {str(e)}" logging.info("禁用自动更新成功完成") return True, "Cursor更新已禁用" except Exception as e: error_msg = f"禁用自动更新失败: {str(e)}" logging.error(error_msg) return False, error_msg def main(): """主函数""" try: # 检查管理员权限 if os.name == 'nt': import ctypes if not is_admin(): logging.warning("当前不是管理员权限运行") print("\n[错误] 请按以下步骤手动操作:") print("1. 按下 Win + R 组合键") print("2. 在运行框中输入 powershell 或 pwsh") print("3. 按 Ctrl + Shift + Enter 以管理员身份运行") print("4. 在管理员终端中输入以下命令:") print(" irm https://github.com/maticarmy/cursor-nosqli-tools/blob/main/scripts/run/cursor_win_id_modifier.ps1 | iex") input("\n按回车键退出...") return print("\n=== Cursor更新禁用测试工具 ===") disabler = CursorUpdateDisabler() success, message = disabler.disable_auto_update() if success: print("\n更新已禁用!") else: print(f"\n禁用更新失败: {message}") except Exception as e: logging.error(f"程序执行出错: {str(e)}") print(f"\n程序执行出错: {str(e)}") finally: input("\n按回车键退出...") if __name__ == "__main__": main()