151 lines
5.7 KiB
Python
151 lines
5.7 KiB
Python
import os
|
||
import sys
|
||
import sqlite3
|
||
import requests
|
||
import urllib3
|
||
import shutil
|
||
import subprocess
|
||
import stat
|
||
import getpass
|
||
import time
|
||
from datetime import datetime
|
||
from typing import Optional, Dict, Tuple
|
||
from logger import logger
|
||
|
||
class UpdateDisabler:
|
||
"""更新禁用模块"""
|
||
|
||
def __init__(self, updater_path: str = None):
|
||
"""
|
||
初始化更新禁用器
|
||
:param updater_path: 可选,updater目录路径
|
||
"""
|
||
# 设置基础路径
|
||
localappdata = os.getenv('LOCALAPPDATA')
|
||
if not localappdata:
|
||
raise EnvironmentError("LOCALAPPDATA 环境变量未设置")
|
||
|
||
self.updater_path = updater_path or os.path.join(localappdata, 'cursor-updater')
|
||
self._callback = None
|
||
self.logger = logger.get_logger("UpdateDisable")
|
||
|
||
def set_progress_callback(self, callback) -> None:
|
||
"""设置进度回调函数"""
|
||
self._callback = callback
|
||
|
||
def _update_progress(self, status: str, message: str) -> None:
|
||
"""更新进度信息"""
|
||
if self._callback:
|
||
self._callback({"status": status, "message": message})
|
||
|
||
def _ensure_parent_dir_exists(self):
|
||
"""确保父目录存在"""
|
||
parent_dir = os.path.dirname(self.updater_path)
|
||
if not os.path.exists(parent_dir):
|
||
os.makedirs(parent_dir, exist_ok=True)
|
||
|
||
def disable(self) -> bool:
|
||
"""
|
||
禁用自动更新
|
||
:return: 是否成功
|
||
"""
|
||
try:
|
||
self._update_progress("start", "开始禁用自动更新...")
|
||
|
||
# 确保父目录存在
|
||
self._ensure_parent_dir_exists()
|
||
|
||
# 检查并删除现有文件或目录
|
||
self._update_progress("checking", "检查现有文件...")
|
||
try:
|
||
if os.path.exists(self.updater_path):
|
||
self._update_progress("removing", "删除现有文件...")
|
||
if os.path.isfile(self.updater_path):
|
||
os.remove(self.updater_path)
|
||
else:
|
||
shutil.rmtree(self.updater_path, ignore_errors=True)
|
||
self.logger.info(f"已删除: {self.updater_path}")
|
||
else:
|
||
self.logger.info("目标路径不存在,将创建新文件")
|
||
except Exception as e:
|
||
self.logger.warning(f"删除操作异常: {str(e)}")
|
||
|
||
# 等待文件系统操作完成
|
||
time.sleep(1)
|
||
|
||
# 创建阻止更新的文件
|
||
self._update_progress("creating", "创建阻止文件...")
|
||
try:
|
||
# 再次确保路径不存在
|
||
if os.path.exists(self.updater_path):
|
||
os.remove(self.updater_path)
|
||
|
||
# 创建新文件
|
||
with open(self.updater_path, 'w') as f:
|
||
f.write("")
|
||
self.logger.info("已创建阻止文件")
|
||
|
||
# 验证文件是否成功创建
|
||
if not os.path.isfile(self.updater_path):
|
||
raise Exception("文件创建验证失败")
|
||
|
||
except Exception as e:
|
||
raise Exception(f"创建文件失败: {str(e)}")
|
||
|
||
# 设置文件只读属性
|
||
self._update_progress("setting", "设置文件属性...")
|
||
try:
|
||
os.chmod(self.updater_path, stat.S_IREAD)
|
||
except Exception as e:
|
||
self.logger.warning(f"设置只读属性失败: {str(e)}")
|
||
|
||
# 设置文件权限
|
||
self._update_progress("permission", "设置文件权限...")
|
||
try:
|
||
username = getpass.getuser()
|
||
result = subprocess.run(
|
||
['icacls', self.updater_path, '/inheritance:r', '/grant:r', f"{username}:(R)"],
|
||
capture_output=True,
|
||
text=True
|
||
)
|
||
|
||
if result.returncode != 0:
|
||
self.logger.warning(f"设置权限返回值非0: {result.stderr}")
|
||
except Exception as e:
|
||
self.logger.warning(f"设置权限失败: {str(e)}")
|
||
|
||
# 最终验证
|
||
if not os.path.exists(self.updater_path):
|
||
raise Exception("最终验证失败:文件不存在")
|
||
|
||
if os.path.isdir(self.updater_path):
|
||
raise Exception("最终验证失败:创建了目录而不是文件")
|
||
|
||
self._update_progress("complete", "禁用自动更新完成")
|
||
self.logger.info("成功禁用自动更新")
|
||
return True
|
||
|
||
except Exception as e:
|
||
self.logger.error(f"禁用自动更新失败: {str(e)}")
|
||
self._update_progress("error", f"操作失败: {str(e)}")
|
||
self.show_manual_guide()
|
||
return False
|
||
|
||
def show_manual_guide(self) -> str:
|
||
"""
|
||
显示手动操作指南
|
||
:return: 指南内容
|
||
"""
|
||
guide = (
|
||
"自动禁用更新失败,请按以下步骤手动操作:\n"
|
||
"1. 以管理员身份打开 PowerShell\n"
|
||
"2. 执行以下命令:\n"
|
||
f" Remove-Item -Path \"{self.updater_path}\" -Force -Recurse -ErrorAction SilentlyContinue\n"
|
||
f" New-Item -Path \"{self.updater_path}\" -ItemType File -Force\n"
|
||
f" Set-ItemProperty -Path \"{self.updater_path}\" -Name IsReadOnly -Value $true\n"
|
||
f" icacls \"{self.updater_path}\" /inheritance:r /grant:r \"{getpass.getuser()}:(R)\""
|
||
)
|
||
|
||
self.logger.warning("需要手动禁用更新")
|
||
self.logger.info(guide)
|
||
return guide |