docs: 添加涉密文件自检工具实施计划
This commit is contained in:
0
UmiOCR-data/py_src/platform/win32/__init__.py
Normal file
0
UmiOCR-data/py_src/platform/win32/__init__.py
Normal file
48
UmiOCR-data/py_src/platform/win32/key_translator.py
Normal file
48
UmiOCR-data/py_src/platform/win32/key_translator.py
Normal 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)
|
||||
141
UmiOCR-data/py_src/platform/win32/win32_api.py
Normal file
141
UmiOCR-data/py_src/platform/win32/win32_api.py
Normal 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)
|
||||
Reference in New Issue
Block a user