#!/usr/bin/env python3 # 使用系统默认的 python3 运行 ########################################################################################### # 作者:gfdgd xi # 版本:3.0.1 # 更新时间:2022年10月05日 # 感谢:感谢 wine 以及 deepin-wine 团队,提供了 wine 和 deepin-wine 给大家使用,让我能做这个程序 # 基于 Python3 构建 ########################################################################################### import os import sys import time import json import random import api as uengineapi import platform import traceback import webbrowser import subprocess import PyQt5.QtWidgets as QtWidgets # 读取文本文档 def readtxt(path): f = open(path, "r") # 设置文件对象 str = f.read() # 获取内容 f.close() # 关闭文本对象 return str # 返回结果 programPath = os.path.split(os.path.realpath(__file__))[0] # 返回 string information = json.loads(readtxt(f"{programPath}/information.json")) version = information["Version"] thankText = "" helpList = json.loads(readtxt(f"{programPath}/ConfigLanguareRunner-help.json")) for i in information["Contribute"]: thankText += f"{i}\n" programEnv = [ ["($WINEPREFIX)", f"{os.path.expanduser('~')}/.wine"], ["($WINE)", "deepin-wine6-stable"], #["($DANGER)", "0"], ["($DANGER)", "1"], ["($HOME)", os.path.expanduser('~')], ["($PROGRAMPATH)", programPath], ["($VERSION)", version], ["($THANK)", thankText], ["($MAKER)", "gfdgd xi"], ["($COPYRIGHT)", f"©2020~{time.strftime('%Y')} gfdgd xi"], ["($?)", "0"], ["($PLATFORM)", platform.system()], ["($DEBUG)", "1"] #["($DEBUG)", str(int("--debug" in sys.argv))] ] readOnlyEnv = [ "($DANGER)", "($HOME)", "($PROGRAMPATH)", "($VERSION)", "($THANK)", "($MAKER)", "($COPYRIGHT)", "($?)", "($SYSTEM)", "($DEBUG)" ] def FindFile(file, name): for i in os.listdir(file): path = f"{file}/{i}" if os.path.isdir(path): returnPath = FindFile(path, name) if returnPath != None: return returnPath.replace("//", "/") if os.path.isfile(path): if i == name: return path return None def Debug(): if "--debug" in sys.argv: traceback.print_exc() class Command(): # 有风险的命令 dangerCommand = [ "bash", "bat", "download", "reg" ] # 可以被使用的命令 commandList = [ "installdll", "installfont", "installsparkcorefont", "installmono", "installgecko", "installvcpp", "installnet", "installmsxml", "echo", "info", "error", "warning", "exit", "bash", "bat", "version", "thank", "pause", "download", "installdxvk", "createbotton", "reg", "enabledopengl", "disbledopengl", "winecfg", "winver", "changeversion", "stopdll", "cat", "taskmgr", "control", "killall", "killallwineserver", "enabledhttpproxy", "disbledhttpproxy", "enabledwinecrashdialog", "disbledwinecrashdialog", "disbledWinebottlecreatelink", "enabledWinebottlecreatelink", "installvb", "installother", "decompressionbottle", "programforum", "installmsi", "installapk" ] def __init__(self, commandString: str) -> None: self.commandString = commandString # 解析器 # 命令字符串转可供解析的列表 def GetCommandList(self) -> list: shellList = [] shellFirstShell = self.commandString.split("\n") # 转换成可以执行的数组 for l in range(0, len(shellFirstShell)): i = shellFirstShell[l] # 判断有没有注释 if "#" in i: # 忽略注释 i = i[:i.index("#")] # 删除前后空格 i = i.strip() # 如果是空行 if i == "": # 忽略此行,此行不做处理 continue # 空格转义 i = i.replace("\\ ", "@Space@") # 解析 i = i.split() # 判断是否为合法的参数,否则提示并忽略 if not i[0] in self.commandList and i[0][0] != "(": print(f"行{l + 1}命令{i[0]}不存在,忽略") programEnv[9][1] = "-2" continue if programEnv[2][1] == "0" and i[0] in self.dangerCommand: print(f"行{l + 1}命令{i[0]}目前解析器不允许运行,忽略") print("如果需要运行,可以在配置面板开启“允许修改系统”选项(针对GUI用户)") print("或添加参数 --system(终端调用运行用户)") programEnv[9][1] = "-1" continue rightList = [] for k in i: # 处理符号转义 rightList.append(k.replace("@Space@", " ").replace("\\n", "\n").replace("\\r", "\r")) shellList.append(rightList) return shellList # 运行器 class Run(): close = False programPath = os.path.split(os.path.realpath(__file__))[0] # 返回 string def Exit(self): self.close = True return 0 def InstallDll(self) -> int: import InstallDll # 如果是数字 number = False try: int(self.command[1]) number = True except: pass if number: return InstallDll.Download(self.wineBottonPath, InstallDll.GetNameByNumber(int(self.command[1])), InstallDll.GetUrlByNumber(int(self.command[1])), self.wine) return InstallDll.Download(self.wineBottonPath, self.command[1], InstallDll.GetUrlByName(self.command[1]), self.wine) def InstallDxvk(self): if not os.path.exists(f"{programPath}/dxvk"): if os.system(f"7z x \"{programPath}/dxvk.7z\" -o\"{programPath}\""): print("错误:无法解压资源") return 1 os.remove(f"{programPath}/dxvk.7z") return os.system(f"env 'WINE={self.wine}' 'WINE64={self.wine}' 'WINEPREFIX={self.wineBottonPath}' bash '{programPath}/dxvk/auto.sh' install") def Thank(self) -> int: for i in information["Contribute"]: print(i) return 0 def InstallFont(self) -> int: import InstallFont return InstallFont.Download(self.wineBottonPath, int(self.command[1])) def InstallMono(self) -> int: return os.system(f"ENTERNOTSHOW=0 '{self.programPath}/InstallMono.py' '{self.wineBottonPath}' '{self.wine}' mono") def InstallGecko(self) -> int: return os.system(f"ENTERNOTSHOW=0 '{self.programPath}/InstallMono.py' '{self.wineBottonPath}' '{self.wine}' gecko") def InstallVCPP(self) -> int: import InstallVisualCPlusPlus return InstallVisualCPlusPlus.Download(self.wineBottonPath, int(self.command[1]), self.wine) def InstallNet(self) -> int: import InstallNetFramework return InstallNetFramework.Download(self.wineBottonPath, int(self.command[1]), self.wine) def InstallMsxml(self) -> int: import InstallMsxml return InstallMsxml.Download(self.wineBottonPath, int(self.command[1]), self.wine) def Info(self) -> int: QtWidgets.QMessageBox.information(None, self.command[1], self.command[2]) return 0 def StopDll(self) -> int: return os.system(f"WINEPREFIX='{self.wineBottonPath}' '{self.wine}' reg add 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v {os.path.splitext(self.command[1])[0]} /f") def CreateBotton(self): self.command = ["bat", "exit"] self.Bat() return 0 def InstallSparkCoreFont(self): if not os.system("which aptss"): # 最新版本星火应用商店处理 os.system("pkexec bash aptss ssupdate") return os.system("pkexec bash aptss install ms-core-fonts") if not os.system("which ss-apt-fast"): # 稍久的版本 os.system("pkexec ss-apt-fast update") return os.system("pkexec bash ss-apt-fast install ms-core-fonts") # 不知道什么版本的处理方法 if not os.system("which apt-fast"): # 稍久的版本 os.system("pkexec apt-fast update") return os.system("pkexec apt-fast install ms-core-fonts") os.system("pkexec apt update") return os.system("pkexec apt install ms-core-fonts") def Echo(self) -> int: del self.command[0] print(" ".join(self.command)) return 0 def Warning(self): QtWidgets.QMessageBox.warning(None, self.command[1], self.command[2]) return 0 def Error(self): QtWidgets.QMessageBox.critical(None, self.command[1], self.command[2]) return 0 def Bash(self): command = "" for i in self.command[1:]: command += f"'{i}' " return os.system(command) def Bat(self) -> int: # Windows 直接转换为以 cmd 运行 if platform.system() == "Windows": # 直接调用 Bash 函数 return self.Bash() command = ["WINEPREFIX='($WINEPREFIX)'", "($WINE)"] for i in programEnv: for k in range(len(command)): command[k] = command[k].replace(i[0], i[1]) for i in self.command[1:]: command.append(i) commandStr = command[0] + " " for i in command[1:]: commandStr += f"'{i}' " return os.system(commandStr) def Version(self): print(f"版本:{version}") print(f"©2020~{time.strftime('%Y')} RacoonGX 团队,By gfdgd xi") return 0 def Pause(self) -> int: input("按回车键继续……") return 0 def Download(self) -> int: command = f"aria2c -x 16 -s 16 -c '{self.command[1]}' " try: command += f"-d '{self.command[2]}' " command += f"-o '{self.command[3]}' " except: pass return os.system(command) def Reg(self) -> int: self.command = ["bat", "regedit", "/s", self.command[1]] return self.Bat() def EnabledOpenGl(self) -> int: self.command = ["reg", f"z:{programPath}/EnabledOpengl.reg"] return self.Reg() def DisbledOpenGl(self) -> int: self.command = ["reg", f"z:{programPath}/DisabledOpengl.reg"] return self.Reg() def Winver(self): self.command = ["bat", "winver"] return self.Bat() def Winecfg(self): self.command = ["bat", "winecfg"] return self.Bat() def ChangeVersion(self): # 判断是否为正确的版本 if not os.path.exists(f"{programPath}/ChangeWineBottonVersion/{self.command[1]}.reg"): print("错误:您选择的版本错误,目前只支持以下版本") for i in os.listdir(f"{programPath}/ChangeWineBottonVersion"): print(i.replace(".reg", ""), end=" ") print() return 1 self.command = ["reg", f"z:/{programPath}/ChangeWineBottonVersion/{self.command[1]}.reg"] return self.Reg() def Cat(self): try: file = open(self.command[1], "r") print(file.read()) file.close() return 0 except: print("文件读取错误") Debug() return 1 def Taskmgr(self): self.command = ["bat", "taskmgr"] return self.Bat() def Control(self): self.command = ["bat", "control"] return self.Bat() def Killall(self): return os.system(f"killall -9 {self.command[1]}") def KillallWineServer(self): command = ["WINEPREFIX='($WINEPREFIX)'", "($WINE)", "-k"] for i in programEnv: for k in range(len(command)): command[k] = command[k].replace(i[0], i[1]) if "box86" in command[1] or "exagear" in command[1] or "box64" in command[1]: print("不支持此 Wine") return 1 if os.path.exists(command[1]): # 文件存在 command[1] = f"{os.path.dirname(command[1])}/wineserver" else: # 读 which command[1] = f"{os.path.dirname(subprocess.getoutput(f'which {command[1]}').strip())}/wineserver" commandStr = command[0] + " " for i in command[1:]: commandStr += f"'{i}' " return os.system(commandStr) def EnabledWineBottleCreateLink(self): self.command = ["bat", "reg", "delete", "HKEY_CURRENT_USER\Software\Wine\DllOverrides", "/v", "winemenubuilder.exe", "/f"] return self.Bat() def DisbledWineBottleCreateLink(self): self.command = ["bat", "reg", "add", "HKEY_CURRENT_USER\Software\Wine\DllOverrides", "/v", "winemenubuilder.exe", "/f"] return self.Bat() def DisbledWineCrashDialog(self): self.command = ["bat", "reg", "add", "HKEY_CURRENT_USER\Software\Wine\WineDbg", "/v", "ShowCrashDialog", "/t", "REG_DWORD", "/d", "00000000", "/f"] return self.Bat() def EnabledWineCrashDialog(self): self.command = ["bat", "reg", "add", "HKEY_CURRENT_USER\Software\Wine\WineDbg", "/v", "ShowCrashDialog", "/t", "REG_DWORD", "/d", "00000001", "/f"] return self.Bat() def EnabledHttpProxy(self): proxyServerAddress = self.command[1] port = self.command[2] self.command = ["bat", "reg", "add", "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings", "/v", "ProxyEnable", "/t", "REG_DWORD", "/d", "00000001", "/f"] self.Bat() self.command = ["bat", "reg", "add", "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings", "/v", "ProxyServer", "/d", f"{proxyServerAddress}:{port}", "/f"] return self.Bat() def DecompressionBottle(self): tempDebDir = f"/tmp/wine-runner-unpack-deb-{random.randint(0, 1000)}" if os.system(f"dpkg -x '{self.command[1]}' '{tempDebDir}'"): return 1 zippath = FindFile(tempDebDir, "files.7z") if zippath == None: return 2 # 解压文件 os.system(f"mkdir -p '{self.command[2]}'") fi = os.system(f"7z x -y '{zippath}' -o'{self.command[2]}'") os.system(f"rm -rfv '{tempDebDir}'") return fi def DisbledHttpProxy(self): self.command = ["bat", "reg", "add", "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings", "/v", "ProxyEnable", "/t", "REG_DWORD", "/d", "00000000", "/f"] return self.Bat() def InstallVB(self): import InstallVisualBasicRuntime return InstallVisualBasicRuntime.Download(self.wineBottonPath, int(self.command[1]), self.wine) def InstallOther(self): import InstallOther return InstallOther.Download(self.wineBottonPath, int(self.command[1]), self.wine) def ProgramForum(self): webbrowser.open_new_tab("https://gfdgdxi.flarum.cloud/") return def InstallMSI(self): self.command = ["bat", "msiexec", "/i", self.command[1]] return self.Bat() def InstallApk(self): if os.system("which uengine > /dev/null"): print("未安装 UEngine,无法使用该命令") return 1 apk = uengineapi.APK(self.command[1]) result = apk.install() homePath = os.getenv("HOME") if not os.path.exists(f"{homePath}/.local/share/applications/uengine"): os.makedirs(f"{homePath}/.local/share/applications/uengine") if not os.path.exists(f"{homePath}/.local/share/icons/hicolor/apps"): os.makedirs(f"{homePath}/.local/share/icons/hicolor/apps") package = apk.packageName() apk.saveApkIcon(f"{homePath}/.local/share/icons/hicolor/apps/{package}.png") apk.saveDesktopFile(f"{homePath}/.local/share/applications/uengine/{package}.desktop", f"{homePath}/.local/share/icons/hicolor/apps/{package}.png") return result # 可以运行的命令的映射关系 # 可以被使用的命令的映射 commandList = { "installdll": InstallDll, "installfont": InstallFont, "installsparkcorefont": InstallSparkCoreFont, "installmono": InstallMono, "installgecko": InstallGecko, "installvcpp": InstallVCPP, "installnet": InstallNet, "installmsxml": InstallMsxml, "echo": Echo, "info": Info, "warning": Warning, "error": Error, "exit": Exit, "bash": Bash, "bat": Bat, "version": Version, "thank": Thank, "pause": Pause, "download": Download, "installdxvk": InstallDxvk, "createbotton": CreateBotton, "reg": Reg, "enabledopengl": EnabledOpenGl, "disbledopengl": DisbledOpenGl, "winecfg": Winecfg, "winver": Winver, "changeversion": ChangeVersion, "stopdll": StopDll, "cat": Cat, "taskmgr": Taskmgr, "control": Control, "killallwineserver": KillallWineServer, "enabledhttpproxy": EnabledHttpProxy, "disbledhttpproxy": DisbledHttpProxy, "enabledwinecrashdialog": EnabledWineCrashDialog, "disbledwinecrashdialog": DisbledWineCrashDialog, "disbledWinebottlecreatelink": DisbledWineBottleCreateLink, "enabledWinebottlecreatelink": EnabledWineBottleCreateLink, "installvb": InstallVB, "installother": InstallOther, "decompressionbottle": DecompressionBottle, "programforum": ProgramForum, "installmsi": InstallMSI, "installapk": InstallApk } # 参数数列表 commandInfo = { "killall": [1], "installdll": [1], "installfont": [1], "installsparkcorefont": [0], "installmono": [0], "installgecko": [0], "installvcpp": [1], "installnet": [1], "installmsxml": [1], "echo": [1], "info": [2], "warning": [2], "error": [2], "exit": [0], "bash": [1], "bat": [1], "version": [0], "thank": [0], "pause": [0], "download": [1], "installdxvk": [0], "createbotton": [0], "reg": [1], "enabledopengl": [0], "disbledopengl": [0], "winecfg": [0], "winver": [0], "changeversion": [1], "stopdll": [1], "cat": [1], "taskmgr": [0], "control": [0], "killallwineserver": [0], "enabledhttpproxy": [2], "disbledhttpproxy": [0], "enabledwinecrashdialog": [0], "disbledwinecrashdialog": [0], "disbledWinebottlecreatelink": [0], "enabledWinebottlecreatelink": [0], "installvb": [1], "installother": [1], "decompressionbottle": [2], "programforum": [0], "installmsi": [1], "installapk": [1] } windowsUnrun = [ "createbotton", "installdll", "installmono", "installgecko", "winecfg", "stopdll", "changeversion", "enabledopengl", "disbledopengl", "installdxvk", "installfont", "installsparkcorefont", "decompressionbottle", "installapk" ] # 解析 def __init__(self, command: list, wineBottonPath: str, wine: str) -> int: self.wineBottonPath = wineBottonPath self.wine = wine for i in command: self.command = i # 变量解析 if self.command[0][0] == "(" and "=" in self.command[0]: env = i[0][: i[0].index("=")] value = i[0][i[0].index("=") + 1:] # 判断是不是只读变量 if env in readOnlyEnv: print(f"运行命令{' '.join(self.command)}出现错误") print(f"变量 {env} 只读,无法修改,忽略") continue change = False for k in range(len(programEnv)): # 修改变量 if env == programEnv[k][0]: programEnv[k][1] = value change = True break if not change: # 添加变量 programEnv.append([f"{env}", value]) continue # 解析命令是否可以在 Windows 使用(只限在 Windows 系统时) if platform.system() == "Windows" and i[0] in self.windowsUnrun: print("此命令不支持在 Windows 上运行") programEnv[9][1] = "-5" continue # 获取程序帮助信息 try: if i[1] == "--help": print(helpList[i[0]].replace("\\n", "\n")) continue except: pass # 正常命令解析 if len(i) -1 < self.commandInfo[i[0]][0]: print("参数不足") programEnv[9][1] = "-3" continue # 替换环境变量 for a in range(1, len(i)): for b in programEnv: if b[0] in i[a]: i[a] = i[a].replace(b[0], b[1]) try: commandReturn = self.commandList[i[0]](self) except: traceback.print_exc() commandReturn = 1 if commandReturn: print(f"运行命令{' '.join(self.command)}出现错误,返回值:", commandReturn) programEnv[9][1] = str(commandReturn) if self.close: break app = QtWidgets.QApplication(sys.argv) if os.getenv("WINE") != None: programEnv[1][1] = os.getenv("WINE") if os.getenv("WINEPREFIX") != None: programEnv[0][1] = os.getenv("WINEPREFIX") if __name__ == "__main__": optionAll = 0 if "--debug" in sys.argv: optionAll += 1 if "--system" in sys.argv: programEnv[2][1] = "1" optionAll += 1 if len(sys.argv) - optionAll < 2: print("Wine 运行器自动配置文件解析器交互环境") print(f"版本:{version}") print(f"©2020~{time.strftime('%Y')} RacoonGX 团队,By gfdgd xi") print("--------------------------------------------------------------") while True: commandLine = input(">") if commandLine == "exit": break com = Command(commandLine) com.Run(com.GetCommandList(), programEnv[0][1], programEnv[1][1]) sys.exit(int(programEnv[9][1])) # 读取文件 try: file = open(sys.argv[1], "r") com = Command(file.read()) file.close() except: print("错误:无法读取该文件,无法继续") sys.exit(1) print("UEngine 运行器自动配置文件解析器") print(f"版本:{version}") print(f"©2020~{time.strftime('%Y')} gfdgd xi") print("--------------------------------------------------------------") com.Run(com.GetCommandList(), programEnv[0][1], programEnv[1][1]) sys.exit(int(programEnv[9][1]))