docs: 添加涉密文件自检工具实施计划

This commit is contained in:
2026-06-08 13:53:24 +08:00
commit 31161d9a5f
1838 changed files with 455407 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
# 负责 pynput 的按键转换
# 封装 keyTranslator 负责key、char、vk的转换
from pynput._util.win32 import KeyTranslator
from umi_log import logger
# ==================== 按键转换器 ====================
# 封装 keyTranslator 负责key、char、vk的转换
class _KeyTranslatorApi:
def __init__(self):
self._kt = KeyTranslator()
self._layout, _layoutData = self._kt._generate_layout()
self._normalLayout = _layoutData[
(False, False, False)
] # 选取常规布局,不受修饰键影响
def __call__(self, key):
"""传入pynput的Key对象返回与修饰键无关的键名char"""
# 比如就算按下Shift再按“=”,依然返回“=”而不是“+”
try:
if hasattr(key, "name"): # 若为控制键
name = key.name.replace("cmd", "win") # win键名称修正
if "_" in name: # 清除 _l _r 标记后缀
name = name.split("_", 1)[0].lower()
return name.lower()
else: # 若为非控制键通过vk获取键名避免组合键的char为空
scan = self._kt._to_scan(key.vk, self._layout) # vk转扫描码
char = self._normalLayout[scan][0] # 扫描码转char
return char.lower()
except Exception: # 特殊键如Fn没有对应字符会跳到这里
if key and hasattr(key, "vk"):
return f"<{key.vk}>" # 未知键值,无对应字符,返回键值本身
else:
logger.error(
f"键值转换异常未知键值key: {str(key)}, type: {type(key)}.",
exc_info=True,
stack_info=True,
)
return str(key)
_KTA = _KeyTranslatorApi()
def getKeyName(key): # 键值转键名
return _KTA(key)

View File

@@ -0,0 +1,141 @@
# ==============================================
# =============== Windows系统API ===============
# ==============================================
import os
import subprocess
from PySide2.QtCore import QStandardPaths as Qsp, QFile, QFileInfo
from umi_log import logger
from umi_about import UmiAbout
from .key_translator import getKeyName
# 环境的类型:
# "APPDATA" 用户,低权限要求
# "ProgramData" 全局,高权限要求
EnvType = "APPDATA" # or "ProgramData"
# ==================== 快捷方式 ====================
class _Shortcut:
@staticmethod # 获取地址
def _getPath(position):
# 桌面
if position == "desktop":
return Qsp.writableLocation(Qsp.DesktopLocation)
startMenu = os.path.join(
os.getenv(EnvType), "Microsoft", "Windows", "Start Menu"
)
# 开始菜单
if position == "startMenu":
return startMenu
# 开机自启
elif position == "startup":
return os.path.join(startMenu, "Programs", "Startup")
# 创建快捷方式返回成功与否的字符串。position取值
# desktop 桌面
# startMenu 开始菜单
# startup 开机自启
@staticmethod
def createShortcut(position):
lnkName = UmiAbout["name"]
appPath = UmiAbout["app"]["path"]
if not appPath or not os.path.exists(appPath):
return f"[Error] 未找到程序exe文件。请尝试手动创建快捷方式。\n[Error] Exe path not exist. Please try creating a shortcut manually.\n\n{appPath}"
lnkPathBase = _Shortcut._getPath(position)
lnkPathBase = os.path.join(lnkPathBase, lnkName)
lnkPath = lnkPathBase + ".lnk"
i = 1
while os.path.exists(lnkPath): # 快捷方式已存在
lnkPath = lnkPathBase + f" ({i}).lnk" # 添加序号
i += 1
appFile = QFile(appPath)
res = appFile.link(lnkPath)
if not res:
return f"[Error] {appFile.errorString()}\n请尝试以管理员权限启动软件。\nPlease try starting the software as an administrator.\nappPath: {appPath}\nlnkPath: {lnkPath}"
return "[Success]"
# 删除快捷方式,返回删除文件的个数
@staticmethod
def deleteShortcut(position):
lnkName = UmiAbout["name"]
lnkDir = _Shortcut._getPath(position)
num = 0
for fileName in os.listdir(lnkDir):
lnkPath = os.path.join(lnkDir, fileName)
try:
if not os.path.isfile(lnkPath): # 排除非文件
continue
info = QFileInfo(lnkPath)
if not info.isSymLink(): # 排除非快捷方式
continue
originName = os.path.basename(info.symLinkTarget())
if lnkName in originName: # 快捷方式指向的文件名包含appName删之
os.remove(lnkPath)
num += 1
except Exception:
logger.error(
f"删除快捷方式失败。 lnkPath: {lnkPath}",
exc_info=True,
stack_info=True,
)
continue
return num
# ==================== 硬件控制 ====================
class _HardwareCtrl:
# 关机
@staticmethod
def shutdown():
os.system("shutdown /s /t 0")
# 休眠
@staticmethod
def hibernate():
os.system("shutdown /h")
# ==================== 对外接口 ====================
class Api:
# 快捷方式。接口: createShortcut deleteShortcut
# 参数:快捷方式位置, desktop startMenu startup
Shortcut = _Shortcut()
# 硬件控制。接口: shutdown hibernate
HardwareCtrl = _HardwareCtrl()
# 根据系统及硬件,判断最适合的渲染器类型
@staticmethod
def getOpenGLUse():
import platform
# 判断系统版本,若 >win10 则使用 GLES ,否则使用软渲染
version = platform.version()
if "." in version:
ver = version.split(".")[0]
if ver.isdigit() and int(ver) >= 10:
return "AA_UseOpenGLES"
return "AA_UseSoftwareOpenGL"
# 键值转键名
@staticmethod
def getKeyName(key):
return getKeyName(key)
# 让系统运行一个程序,不堵塞当前进程
@staticmethod
def runNewProcess(path, args=""):
subprocess.Popen(
f'start "" "{path}" {args}',
shell=True,
# 确保在一个新的控制台窗口中运行,与当前进程完全独立。
creationflags=subprocess.CREATE_NEW_CONSOLE,
)
# 用系统默认应用打开一个文件或目录,不堵塞当前进程
@staticmethod
def startfile(path):
os.startfile(path)