142 lines
4.8 KiB
Python
142 lines
4.8 KiB
Python
# ==============================================
|
||
# =============== 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)
|