9 Star 128 Fork 23

gfdgd xi / Wine 运行器

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
main-newgui.py 60.47 KB
一键复制 编辑 原始数据 按行查看 历史
gfdgd xi 提交于 2023-04-24 21:42 . change
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221
#!/usr/bin/env python3
# 使用系统默认的 python3 运行
###########################################################################################
# 作者:gfdgd xi
# 版本:1.6.1
# 更新时间:2022年07月11日
# 感谢:感谢 wine 以及 deepin-wine 团队,提供了 wine 和 deepin-wine 给大家使用,让我能做这个程序
# 基于 Python3 的 tkinter 构建
###########################################################################################
#################
# 引入所需的库
#################
import os
import sys
import time
import json
import shutil
import easygui
import req as requests
import threading
import traceback
import ttkthemes
import webbrowser
import subprocess
import ttkbootstrap
import tkinter as tk
import tkinter.ttk as ttk
import tkinter.filedialog
import tkinter.messagebox
import PIL.Image as Image
import PIL.ImageTk as ImageTk
###################
# 程序所需事件
###################
# 打开程序官网
def OpenProgramURL():
webbrowser.open_new_tab(programUrl)
# 读取文本文档
def readtxt(path):
f = open(path, "r") # 设置文件对象
str = f.read() # 获取内容
f.close() # 关闭文本对象
return str # 返回结果
# 写入文本文档
def write_txt(path, things):
file = open(path, 'w', encoding='UTF-8') # 设置文件对象
file.write(things) # 写入文本
file.close() # 关闭文本对象
# 获取用户桌面目录
def get_desktop_path():
for line in open(get_home() + "/.config/user-dirs.dirs"): # 以行来读取配置文件
desktop_index = line.find("XDG_DESKTOP_DIR=\"") # 寻找是否有对应项,有返回 0,没有返回 -1
if desktop_index != -1: # 如果有对应项
break # 结束循环
if desktop_index == -1: # 如果是提前结束,值一定≠-1,如果是没有提前结束,值一定=-1
return -1
else:
get = line[17:-2] # 截取桌面目录路径
get_index = get.find("$HOME") # 寻找是否有对应的项,需要替换内容
if get != -1: # 如果有
get = get.replace("$HOME", get_home()) # 则把其替换为用户目录(~)
return get # 返回目录
# 获取用户主目录
def get_home():
return os.path.expanduser('~')
# 第一个浏览按钮事件
def liulanbutton():
path = tkinter.filedialog.askdirectory(title="选择 wine 容器", initialdir=json.loads(readtxt(get_home() + "/.config/deepin-wine-runner/WineBotton.json"))["path"])
if path != "" and path != "()":
e1.set(path)
write_txt(get_home() + "/.config/deepin-wine-runner/WineBotton.json", json.dumps({"path": path})) # 写入配置文件
# 第二个浏览按钮事件
def liulanexebutton():
path = tkinter.filedialog.askopenfilename(title="选择 exe 可执行文件", filetypes=[("exe 可执行文件", "*.exe"), ("EXE 可执行文件", "*.EXE"), ("所有文件", "*.*")], initialdir=json.loads(readtxt(get_home() + "/.config/deepin-wine-runner/FindExe.json"))["path"])
if path != "" and path != "()":
e2.set(path) # 显示路径
write_txt(get_home() + "/.config/deepin-wine-runner/FindExe.json", json.dumps({"path": os.path.dirname(path)})) # 写入配置文件
# 使用多线程运行可执行文件
def runexebutton():
run = threading.Thread(target=runexebutton_threading)
run.start()
def DisableButton(things):
a = {True: tk.DISABLED, False: tk.NORMAL}
button1.configure(state=a[things])
button2.configure(state=a[things])
button3.configure(state=a[things])
wineConfig.configure(state=a[things])
e1.configure(state=a[things])
e2.configure(state=a[things])
o1.configure(state=a[things])
#winetricksOpen.configure(state=a[things])
getProgramIcon.configure(state=a[things])
uninstallProgram.configure(state=a[things])
trasButton.configure(state=a[things])
def CheckProgramIsInstall(program):
return not bool(os.system(f"which '{program}'"))
# 运行可执行文件的线程
def runexebutton_threading():
DisableButton(True)
if not CheckProgramIsInstall(wine[o1_text.get()]):
if not tkinter.messagebox.askyesno(title="提示", message="检查到您未安装这个 wine,是否继续使用这个 wine 运行?"):
DisableButton(False)
return
if e2.get() == "": # 判断文本框是否有内容
tkinter.messagebox.showinfo(title="提示", message="没有填写需要使用的 exe 应用")
DisableButton(False)
return
else: # 如果都有
if e1.get() == "":
wineBottonPath = setting["DefultBotton"]
else:
wineBottonPath = e1.get()
option = ""
if setting["Architecture"] != "Auto":
option += f"WINEARCH={setting['Architecture']} "
if not setting["Debug"]:
option += "WINEDEBUG=-all "
if setting["TerminalOpen"]:
res = subprocess.Popen([f"'{programPath}/launch.sh' deepin-terminal -C \"WINEPREFIX='" + wineBottonPath + "' " + option + wine[o1_text.get()] + " '" + e2.get() + "' " + setting["WineOption"] + "\" --keep-open"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
else:
res = subprocess.Popen(["WINEPREFIX='" + wineBottonPath + "' " + option + wine[o1_text.get()] + " '" + e2.get() + "' " + setting["WineOption"]], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
# 清空文本框内容
returnText.config(state=tk.NORMAL)
returnText.delete(1.0, "end")
returnText.config(state=tk.DISABLED)
# 实时读取程序返回
while res.poll() is None:
returnText.config(state=tk.NORMAL)
try:
text = res.stdout.readline().decode("utf8")
except:
text = ""
returnText.insert("end", text)
print(text)
returnText.config(state=tk.DISABLED)
findExeHistory.append(wineBottonPath) # 将记录写进数组
wineBottonHistory.append(e2.get()) # 将记录写进数组
write_txt(get_home() + "/.config/deepin-wine-runner/FindExeHistory.json", str(json.dumps(ListToDictionary(findExeHistory)))) # 将历史记录的数组转换为字典并写入
write_txt(get_home() + "/.config/deepin-wine-runner/WineBottonHistory.json", str(json.dumps(ListToDictionary(wineBottonHistory)))) # 将历史记录的数组转换为字典并写入
e1['value'] = findExeHistory
e2['value'] = wineBottonHistory
DisableButton(False)
# 显示“关于这个程序”窗口
def about_this_program()->"显示“关于这个程序”窗口":
global about
global title
global iconPath
mess = tk.Toplevel()
message = ttk.Frame(mess)
mess.resizable(0, 0)
mess.title("关于 {}".format(title))
mess.iconphoto(False, tk.PhotoImage(file=iconPath))
img = ImageTk.PhotoImage(Image.open(iconPath))
label1 = ttk.Label(message, image=img)
label2 = ttk.Label(message, text=about)
button1 = ttk.Button(message, text="确定", command=mess.withdraw)
label1.pack()
label2.pack()
button1.pack(side="bottom")
message.pack()
mess.mainloop()
# 显示“提示”窗口
def helps():
global tips
tkinter.messagebox.showinfo(title="提示", message=tips)
# 显示更新内容窗口
def UpdateThings():
tkinter.messagebox.showinfo(title="更新内容", message=updateThings)
# 生成 desktop 文件在启动器
def make_desktop_on_launcher():
if combobox1.get() == "" or e2.get() == "": # 判断文本框是否有内容
tkinter.messagebox.showinfo(title="提示", message="没有填写需要使用 exe 应用或保存的文件名")
if not CheckProgramIsInstall(wine[o1_text.get()]):
if not tkinter.messagebox.askyesno(title="提示", message="检查到您未安装这个 wine,是否继续使用这个 wine 写入?"):
DisableButton(False)
return
else: # 如果都有
if os.path.exists(get_home() + "/.local/share/applications/" + combobox1.get() + ".desktop"): # 判断目录是否有该文件,如果有
choose = tkinter.messagebox.askokcancel(title="提示", message="文件已经存在,是否覆盖?") # 询问用户是否覆盖
if choose: # 如要覆盖
os.remove(get_home() + "/.local/share/applications/" + combobox1.get() + ".desktop") # 删除该文件
else: # 如不覆盖
return # 结束
if e1.get() == "":
wineBottonPath = setting["DefultBotton"]
else:
wineBottonPath = e1.get()
option = ""
if setting["Architecture"] != "Auto":
option += f"WINEARCH={setting['Architecture']} "
if not setting["Debug"]:
option += "WINEDEBUG=-all "
write_txt(get_home() + "/.local/share/applications/" + combobox1.get() + ".desktop", f'''[Desktop Entry]
Name={combobox1.get()}
Exec=env WINEPREFIX='{wineBottonPath}' {option} {wine[o1_text.get()]} '{e2.get()}' {setting["WineOption"]}
Icon={iconPath}
Type=Application
StartupNotify=true''') # 写入文本文档
shellHistory.append(combobox1.get()) # 将记录写进数组
write_txt(get_home() + "/.config/deepin-wine-runner/ShellHistory.json", str(json.dumps(ListToDictionary(shellHistory)))) # 将历史记录的数组转换为字典并写入
combobox1['value'] = shellHistory
tkinter.messagebox.showinfo(title="提示", message="生成完成!") # 显示完成对话框
# 生成 desktop 文件在桌面
# (第四个按钮的事件)
def make_desktop_on_desktop():
if combobox1.get() == "" or e2.get() == "": # 判断文本框是否有内容
tkinter.messagebox.showinfo(title="提示", message="没有填写需要使用的 exe 应用或保存的文件名")
if not CheckProgramIsInstall(wine[o1_text.get()]):
if not tkinter.messagebox.askyesno(title="提示", message="检查到您未安装这个 wine,是否继续使用这个 wine 写入?"):
DisableButton(False)
return
else: # 如果都有
if os.path.exists(get_desktop_path() + "/" + combobox1.get() + ".desktop"): # 判断目录是否有该文件,如果有
choose = tkinter.messagebox.askokcancel(title="提示", message="文件已经存在,是否覆盖?") # 询问用户是否覆盖
if choose: # 如要覆盖
os.remove(get_desktop_path() + "/" + combobox1.get() + ".desktop") # 删除该文件
else: # 如不覆盖
return # 结束
if e1.get() == "":
wineBottonPath = setting["DefultBotton"]
else:
wineBottonPath = e1.get()
os.mknod(get_desktop_path() + "/" + combobox1.get() + ".desktop")
option = ""
if setting["Architecture"] != "Auto":
option += f"WINEARCH={setting['Architecture']} "
if not setting["Debug"]:
option += "WINEDEBUG=-all "
write_txt(get_desktop_path() + "/" + combobox1.get() + ".desktop", f'''[Desktop Entry]
Name={combobox1.get()}
Exec=env WINEPREFIX='{wineBottonPath}' {option} {wine[o1_text.get()]} '{e2.get()}' {setting["WineOption"]}
Icon={iconPath}
Type=Application
StartupNotify=true''') # 写入文本文档
shellHistory.append(combobox1.get()) # 将记录写进数组
write_txt(get_home() + "/.config/deepin-wine-runner/ShellHistory.json", str(json.dumps(ListToDictionary(shellHistory)))) # 将历史记录的数组转换为字典并写入
combobox1['value'] = shellHistory
tkinter.messagebox.showinfo(title="提示", message="生成完成!") # 显示完成对话框
# 数组转字典
def ListToDictionary(list):
dictionary = {}
for i in range(len(list)):
dictionary[i] = list[i]
return dictionary
def CleanProgramHistory():
if tkinter.messagebox.askokcancel(title="警告", message="删除后将无法恢复,你确定吗?\n删除后软件将会自动重启。"):
shutil.rmtree(get_home() + "/.config/deepin-wine-runner")
ReStartProgram()
# 重启本应用程序
def ReStartProgram():
python = sys.executable
os.execl(python, python, * sys.argv)
def KillProgram():
os.system(f"killall {wine[o1_text.get()]} -9")
os.system("killall winedbg -9")
def InstallWine():
threading.Thread(target=os.system, args=[f"'{programPath}/launch.sh' deepin-terminal -e \"{programPath}/AllInstall.py\""]).start()
def OpenWineBotton():
if e1.get() == "":
wineBottonPath = setting["DefultBotton"]
else:
wineBottonPath = e1.get()
os.system("xdg-open \"" + wineBottonPath.replace("\'", "\\\'") + "\"")
def OpenWineFontPath():
if e1.get() == "":
wineBottonPath = setting["DefultBotton"]
else:
wineBottonPath = e1.get()
tkinter.messagebox.showinfo(title="提示", message="如果安装字体?只需要把字体文件复制到此字体目录\n按下“OK”按钮可以打开字体目录")
os.system("xdg-open \"" + wineBottonPath.replace("\'", "\\\'") + "/drive_c/windows/Fonts\"")
def UninstallProgram():
threading.Thread(target=UninstallProgram_threading).start()
def UninstallProgram_threading():
threading.Thread(target=RunWineProgram, args=[programPath + "/geek.exe"]).start()
def ConfigWineBotton():
threading.Thread(target=RunWineProgram, args=["winecfg"]).start()
def RunWineProgram(wineProgram, history = False, Disbled = True):
DisableButton(True)
if not CheckProgramIsInstall(wine[o1_text.get()]):
if not tkinter.messagebox.askyesno(title="提示", message="检查到您未安装这个 wine,是否继续使用这个 wine 运行?"):
DisableButton(False)
return
if e1.get() == "":
wineBottonPath = setting["DefultBotton"]
else:
wineBottonPath = e1.get()
option = ""
if setting["Architecture"] != "Auto":
option += f"WINEARCH={setting['Architecture']} "
if not setting["Debug"]:
option += "WINEDEBUG=-all "
if setting["TerminalOpen"]:
res = subprocess.Popen([f"'{programPath}/launch.sh' deepin-terminal -C \"WINEPREFIX='" + wineBottonPath + "' " + option + wine[o1_text.get()] + " '" + wineProgram + "' " + setting["WineOption"] + "\" --keep-open"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
else:
res = subprocess.Popen(["WINEPREFIX='" + wineBottonPath + "' " + option + wine[o1_text.get()] + " '" + wineProgram + "' " + setting["WineOption"]], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
# 清空文本框内容
returnText.config(state=tk.NORMAL)
returnText.delete(1.0, "end")
returnText.config(state=tk.DISABLED)
# 实时读取程序返回
while res.poll() is None:
returnText.config(state=tk.NORMAL)
try:
text = res.stdout.readline().decode("utf8")
except:
text = ""
returnText.insert("end", text)
print(text)
returnText.config(state=tk.DISABLED)
if history:
findExeHistory.append(wineBottonPath) # 将记录写进数组
wineBottonHistory.append(e2.get()) # 将记录写进数组
write_txt(get_home() + "/.config/deepin-wine-runner/FindExeHistory.json", str(json.dumps(ListToDictionary(findExeHistory)))) # 将历史记录的数组转换为字典并写入
write_txt(get_home() + "/.config/deepin-wine-runner/WineBottonHistory.json", str(json.dumps(ListToDictionary(wineBottonHistory)))) # 将历史记录的数组转换为字典并写入
e1['value'] = findExeHistory
e2['value'] = wineBottonHistory
if Disbled:
DisableButton(False)
def RunWinetricks():
DisableButton(True)
if not CheckProgramIsInstall(wine[o1_text.get()]):
if not tkinter.messagebox.askyesno(title="提示", message="检查到您未安装这个 wine,是否继续使用这个 wine 运行?"):
DisableButton(False)
return
wineBottonPath = setting["DefultBotton"]
if not e1.get() == "":
wineBottonPath = e1.get()
option = ""
if setting["Architecture"] != "Auto":
option += f"WINEARCH={setting['Architecture']} "
if not setting["Debug"]:
option += "WINEDEBUG=-all "
if setting["TerminalOpen"]:
res = subprocess.Popen([f"'{programPath}/launch.sh' deepin-terminal -C \"WINEPREFIX='{wineBottonPath}' {option} WINE=" + subprocess.getoutput(f"which {wine[o1_text.get()]}").replace(" ", "").replace("\n", "") + " winetricks --gui\" --keep-open"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
else:
res = subprocess.Popen([f"WINEPREFIX='{wineBottonPath}' {option} WINE='" + subprocess.getoutput(f"which {wine[o1_text.get()]}").replace(" ", "").replace("\n", "") + "' winetricks --gui"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
#res = subprocess.Popen(["WINEPREFIX='" + option + wineBottonPath + "' winetricks"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
# 清空文本框内容
returnText.config(state=tk.NORMAL)
returnText.delete(1.0, "end")
returnText.config(state=tk.DISABLED)
# 实时读取程序返回
while res.poll() is None:
returnText.config(state=tk.NORMAL)
try:
text = res.stdout.readline().decode("utf8")
except:
text = ""
returnText.insert("end", text)
print(text)
returnText.config(state=tk.DISABLED)
DisableButton(False)
def InstallMonoGecko(program):
DisableButton(True)
if e1.get() == "":
wineBottonPath = setting["DefultBotton"]
else:
wineBottonPath = e1.get()
os.system(f"'{programPath}/launch.sh' deepin-terminal -C \"'{programPath}/InstallMono.py' '{wineBottonPath}' {wine[o1_text.get()]} {program}\" --keep-open")
DisableButton(False)
def InstallNetFramework():
DisableButton(True)
if e1.get() == "":
wineBottonPath = setting["DefultBotton"]
else:
wineBottonPath = e1.get()
os.system(f"'{programPath}/launch.sh' deepin-terminal -C \"'{programPath}/InstallNetFramework.py' '{wineBottonPath}' {wine[o1_text.get()]}\" --keep-open")
DisableButton(False)
def InstallVisualStudioCPlusPlus():
DisableButton(True)
if e1.get() == "":
wineBottonPath = setting["DefultBotton"]
else:
wineBottonPath = e1.get()
os.system(f"'{programPath}/launch.sh' deepin-terminal -C \"'{programPath}/InstallVisualCPlusPlus.py' '{wineBottonPath}' {wine[o1_text.get()]}\" --keep-open")
DisableButton(False)
def InstallMSXML():
DisableButton(True)
if e1.get() == "":
wineBottonPath = setting["DefultBotton"]
else:
wineBottonPath = e1.get()
os.system(f"'{programPath}/launch.sh' deepin-terminal -C \"'{programPath}/InstallMsxml.py' '{wineBottonPath}' {wine[o1_text.get()]}\" --keep-open")
DisableButton(False)
def InstallOther():
DisableButton(True)
if e1.get() == "":
wineBottonPath = setting["DefultBotton"]
else:
wineBottonPath = e1.get()
os.system(f"'{programPath}/launch.sh' deepin-terminal -C \"'{programPath}/InstallOther.py' '{wineBottonPath}' {wine[o1_text.get()]}\" --keep-open")
DisableButton(False)
def BuildExeDeb():
if e1.get() == "":
wineBottonPath = setting["DefultBotton"]
else:
wineBottonPath = e1.get()
threading.Thread(target=os.system, args=[f"python3 '{programPath}/deepin-wine-packager.py' '{wineBottonPath}' '{wine[o1_text.get()]}'"]).start()
def SetDeepinFileDialogDeepin():
code = os.system(f"pkexec \"{programPath}/deepin-wine-venturi-setter.py\" deepin")
if code != 0:
if code == 1:
tkinter.messagebox.showerror(title="错误", message="无法更新配置:配置不准重复配置")
return
tkinter.messagebox.showerror(title="错误", message="配置失败")
def SetDeepinFileDialogDefult():
code = os.system(f"pkexec \"{programPath}/deepin-wine-venturi-setter.py\" defult")
if code != 0:
if code == 1:
tkinter.messagebox.showerror(title="错误", message="无法更新配置:配置不准重复配置")
return
tkinter.messagebox.showerror(title="错误", message="配置失败")
def SetDeepinFileDialogRecovery():
threading.Thread(target=os.system, args=[f"'{programPath}/launch.sh' deepin-terminal -C 'pkexec \"{programPath}/deepin-wine-venturi-setter.py\" recovery' --keep-open"]).start()
def DeleteWineBotton():
if not tkinter.messagebox.askokcancel(title="提示", message="你确定要删除容器吗?删除后将无法恢复!\n如果没有选择 wine 容器,将会自动删除默认的容器!"):
return
if e1.get() == "":
wineBottonPath = setting["DefultBotton"]
else:
wineBottonPath = e1.get()
try:
shutil.rmtree(wineBottonPath)
tkinter.messagebox.showinfo(title="提示", message="删除完毕!")
except:
traceback.print_exc()
tkinter.messagebox.showerror(title="错误", message=traceback.format_exc())
def ThankWindow():
easygui.textbox(title="特别谢明", msg="感谢以下的大佬在 deepin 论坛、公众号等平台提供的 Wine 适配解决方案,现在将这些 Wine 适配方案加入此 Wine 运行器,对此有由衷的感谢!如果有侵犯到您的权利和意愿,请尽快与开发者联系删除在此程序内相关的内容:", text=thankText)
def InstallWineFont():
threading.Thread(target=os.system, args=[f"'{programPath}/launch.sh' deepin-terminal -C 'echo 这些字体来自星火应用商店 && sudo ss-apt-fast install ms-core-fonts winfonts -y' --keep-open"]).start()
def WineRunnerBugUpload():
threading.Thread(target=os.system, args=[programPath + "/deepin-wine-runner-update-bug"]).start()
def GetScreenSize():
screenInformation = []
# 使用 xrandr 进行筛选
for i in subprocess.getoutput("xrandr").split('\n'):
if not " connected " in i: # 检测连接的显示器
continue
# 获取分辨率基本信息,如
# DisplayPort-0 connected 1600x900+1280+0 (normal left inverted right x axis y axis) 434mm x 236mm
# 先判断是否为主屏幕
main = False
if "primary" in i:
main = True
# 进行进一步筛选
i = i[i.index("connected"):].replace("connected", "").replace("primary", "")
# 进行初步筛选,如
# 1600x900+1280+0 (normal left inverted right x axis y axis) 434mm x 236mm
i = i[:i.index("(")].replace(" ", "")
# 筛选为 1600x900+0+0 进行最后数值的提取
screenInformation.append([
int(i[:i.index("x")]), # 获取宽度
int(i[i.index("x") + 1 :i.index("+")]), # 获取高度
int(i[i.index("+") + 1:].split('+')[0]), # 获取显示屏 X 坐标
int(i[i.index("+") + 1:].split('+')[1]), # 获取显示屏 Y 坐标
main # 是否为主屏幕
])
return screenInformation # 返回结果
def UOSPackageScript():
threading.Thread(target=os.system, args=[f"python3 '{programPath}/deepin-wine-packager-with-script.py'"]).start()
def RunVM():
threading.Thread(target=os.system, args=[f"bash '{programPath}/RunVM.sh'"]).start()
class UpdateWindow():
data = {}
def ShowWindow():
update = tk.Toplevel()
update.title("检查更新")
update.resizable(0, 0)
update.iconphoto(False, tk.PhotoImage(file=iconPath))
versionLabel = ttk.Label(update, text="当前版本:{}\n最新版本:未知\n更新内容:".format(version))
updateText = tk.Text(update)
controlFrame = ttk.Frame(update)
ok = ttk.Button(controlFrame, text="更新(更新过程中会关闭所有Python应用,包括这个应用)", command=UpdateWindow.Update)
cancel = ttk.Button(controlFrame, text="取消", command=update.destroy)
try:
UpdateWindow.data = json.loads(requests.get("http://120.25.153.144/spark-deepin-wine-runner/update.json").text)
versionLabel = ttk.Label(update, text="当前版本:{}\n最新版本:{}\n更新内容:".format(version, UpdateWindow.data["Version"]))
if UpdateWindow.data["Version"] == version:
updateText.insert("0.0", "此为最新版本,无需更新")
ok.configure(state=tk.DISABLED)
else:
updateText.insert("0.0", UpdateWindow.data["New"].replace("\\n", "\n"))
except:
traceback.print_exc()
tkinter.messagebox.showerror(title="错误", message="无法连接服务器!")
updateText.configure(state=tk.DISABLED)
versionLabel.pack(anchor=tk.W)
updateText.pack()
controlFrame.pack(anchor=tk.E)
cancel.grid(row=0, column=0)
ok.grid(row=0, column=1)
update.mainloop()
def Update():
if not os.path.exists("/tmp/uengine-runner/update"):
os.makedirs("/tmp/spark-deepin-wine-runner/update")
try:
write_txt("/tmp/spark-deepin-wine-runner/update.sh", f"""#!/bin/bash
echo 删除多余的安装包
rm -rfv /tmp/spark-deepin-wine-runner/update/*
echo 关闭“UEngine 运行器”以及其它“Python 应用”
killall python3
echo 下载安装包
wget -P /tmp/spark-deepin-wine-runner/update {UpdateWindow.data["Url"][0], iconPath}
echo 安装安装包
dpkg -i /tmp/spark-deepin-wine-runner/update/*.deb
echo 修复依赖关系
apt install -f -y
notify-send -i "{iconPath}" "更新完毕!"
zenity --info --text=\"更新完毕!\" --ellipsize
""")
except:
traceback.print_exc()
easygui.textbox(title="错误", msg="更新出现错误,无法继续更新!", text=traceback.format_exc())
os.system(f"'{programPath}/launch.sh' deepin-terminal -e pkexec bash /tmp/spark-deepin-wine-runner/update.sh")
class GetDllFromWindowsISO:
wineBottonPath = get_home() + "/.wine"
isoPath = None#ttk.Entry()
dllList = None
message = None
dllFound = None
dllControl = None
foundButton = None
saveDll = None
setWineBotton = None
browser = None
mount = False
mountButton = None
def ShowWindow():
DisableButton(True)
GetDllFromWindowsISO.message = tk.Toplevel()
if not e1.get() == "":
GetDllFromWindowsISO.wineBottonPath = e1.get()
ttk.Label(GetDllFromWindowsISO.message, text=f"""提示:
目前本提取功能只支持 Windows XP 以及 Windows Server 2003 等老系统的官方安装镜像,只支持读取 i386 安装方法的安装镜像,不支持读取 wim、ghost 安装方式
以及不要拷贝/替换太多的 dll,否则可能会导致 wine 容器异常
最后,拷贝/替换 dll 后,建议点击下面“设置 wine 容器”按钮==》函数库 进行设置
当前选择的 Wine 容器:{GetDllFromWindowsISO.wineBottonPath}""").grid(row=0, column=0, columnspan=3, sticky=tk.W)
ttk.Label(GetDllFromWindowsISO.message, text="ISO镜像:").grid(row=1, column=0, sticky=tk.W)
GetDllFromWindowsISO.isoPath = ttk.Combobox(GetDllFromWindowsISO.message, width=100)
GetDllFromWindowsISO.browser = ttk.Button(GetDllFromWindowsISO.message, text="浏览……", command=GetDllFromWindowsISO.Browser)
isoControl = ttk.Frame(GetDllFromWindowsISO.message)
GetDllFromWindowsISO.mountButton = ttk.Button(isoControl, text="读取/挂载ISO镜像", command=GetDllFromWindowsISO.MountDisk)
ttk.Button(isoControl, text="关闭/卸载ISO镜像", command=GetDllFromWindowsISO.UmountDisk).grid(row=0, column=1)
ttk.Label(GetDllFromWindowsISO.message, text="查找DLL\n(为空则代表不查找,\n将显示全部内容):").grid(row=3, column=0)
GetDllFromWindowsISO.dllFound = ttk.Combobox(GetDllFromWindowsISO.message, width=100)
GetDllFromWindowsISO.foundButton = ttk.Button(GetDllFromWindowsISO.message, text="查找", command=GetDllFromWindowsISO.Found)
GetDllFromWindowsISO.dllList = tk.Listbox(GetDllFromWindowsISO.message, width=100)
GetDllFromWindowsISO.dllControl = ttk.Frame(GetDllFromWindowsISO.message)
GetDllFromWindowsISO.saveDll = ttk.Button(GetDllFromWindowsISO.dllControl, text="保存到 wine 容器中", command=GetDllFromWindowsISO.CopyDll)
GetDllFromWindowsISO.setWineBotton = ttk.Button(GetDllFromWindowsISO.dllControl, text="设置 wine 容器", command=lambda: threading.Thread(target=RunWineProgram, args=["winecfg", False, False]).start())
# 设置控件
GetDllFromWindowsISO.DisbledDown(True)
GetDllFromWindowsISO.isoPath['value'] = isoPath
GetDllFromWindowsISO.dllFound['value'] = isoPathFound
# 显示控件
GetDllFromWindowsISO.isoPath.grid(row=1, column=1)
GetDllFromWindowsISO.browser.grid(row=1, column=2)
GetDllFromWindowsISO.mountButton.grid(row=0, column=0)
isoControl.grid(row=2, column=0, columnspan=3)
GetDllFromWindowsISO.dllFound.grid(row=3, column=1)
GetDllFromWindowsISO.foundButton.grid(row=3, column=2)
GetDllFromWindowsISO.dllList.grid(row=4, column=0, columnspan=3)
GetDllFromWindowsISO.dllControl.grid(row=5, column=0, columnspan=3)
GetDllFromWindowsISO.saveDll.grid(row=0, column=0)
GetDllFromWindowsISO.setWineBotton.grid(row=0, column=1)
# 设置
GetDllFromWindowsISO.message.protocol('WM_DELETE_WINDOW', GetDllFromWindowsISO.ExitWindow)
GetDllFromWindowsISO.message.title(f"Wine 运行器 {version}——从 ISO 提取 DLL")
# 显示
GetDllFromWindowsISO.message.mainloop()
def DisbledUp(state):
nd = [tk.NORMAL, tk.DISABLED]
GetDllFromWindowsISO.isoPath.configure(state=nd[int(state)])
GetDllFromWindowsISO.browser.configure(state=nd[int(state)])
GetDllFromWindowsISO.mountButton.configure(state=nd[int(state)])
def DisbledDown(state):
nd = [tk.NORMAL, tk.DISABLED]
GetDllFromWindowsISO.dllList.configure(state=nd[int(state)])
GetDllFromWindowsISO.dllFound.configure(state=nd[int(state)])
#GetDllFromWindowsISO.dllControl.configure(state=nd[int(state)])
GetDllFromWindowsISO.saveDll.configure(state=nd[int(state)])
GetDllFromWindowsISO.setWineBotton.configure(state=nd[int(state)])
GetDllFromWindowsISO.foundButton.configure(state=nd[int(state)])
def Browser():
path = tkinter.filedialog.askopenfilename(title="选择 ISO 镜像文件",
filetypes=[("ISO 镜像文件", "*.iso"), ("ISO 镜像文件", "*.ISO"), ("所有文件", "*.*")],
initialdir=json.loads(readtxt(get_home() + "/.config/deepin-wine-runner/FindISO.json"))["path"])
if path == None or path == "":
return
GetDllFromWindowsISO.isoPath.set(path)
write_txt(get_home() + "/.config/deepin-wine-runner/FindISO.json", json.dumps({"path": os.path.dirname(path)})) # 写入配置文件
def Found():
found = GetDllFromWindowsISO.dllFound.get()
GetDllFromWindowsISO.dllList.configure(state=tk.NORMAL)
GetDllFromWindowsISO.dllList.delete(0, tk.END)
try:
if found == "":
for i in os.listdir("/tmp/wine-runner-getdll/i386"):
if i[-3:] == "dl_":
GetDllFromWindowsISO.dllList.insert("end", i[:-1] + "l")
return
for i in os.listdir("/tmp/wine-runner-getdll/i386"):
if found in i[:-1] + "l":
GetDllFromWindowsISO.dllList.insert("end", i[:-1] + "l")
isoPathFound.append(found) # 将记录写进数组
write_txt(get_home() + "/.config/deepin-wine-runner/ISOPathFound.json", str(json.dumps(ListToDictionary(isoPathFound)))) # 将历史记录的数组转换为字典并写入
GetDllFromWindowsISO.dllFound['value'] = isoPathFound
except:
traceback.print_exc()
tkinter.messagebox.showerror(title="错误", message=traceback.format_exc())
def ExitWindow():
if GetDllFromWindowsISO.mount:
tkinter.messagebox.showinfo(title="提示", message="请关闭/卸载镜像后再关闭本窗口")
return
DisableButton(False)
GetDllFromWindowsISO.message.destroy()
def MountDisk():
if not os.path.exists(GetDllFromWindowsISO.isoPath.get()):
tkinter.messagebox.showerror(title="错误", message="您选择的 ISO 镜像文件不存在")
return
if os.path.exists("/tmp/wine-runner-getdll"):
try:
os.rmdir("/tmp/wine-runner-getdll")
except:
# 如果无法删除可能是挂载了文件
os.system("pkexec umount /tmp/wine-runner-getdll")
try:
os.rmdir("/tmp/wine-runner-getdll")
except:
traceback.print_exc()
tkinter.messagebox.showerror(title="错误", message=traceback.format_exc())
return
os.makedirs("/tmp/wine-runner-getdll")
GetDllFromWindowsISO.dllList.configure(state=tk.NORMAL)
os.system(f"pkexec mount '{GetDllFromWindowsISO.isoPath.get()}' /tmp/wine-runner-getdll")
GetDllFromWindowsISO.dllList.delete(0, tk.END)
try:
for i in os.listdir("/tmp/wine-runner-getdll/i386"):
if i[-3:] == "dl_":
GetDllFromWindowsISO.dllList.insert("end", i[:-1] + "l")
except:
traceback.print_exc()
tkinter.messagebox.showerror(title="错误", message=f"镜像内容读取/挂载失败,报错如下:\n{traceback.format_exc()}")
return
GetDllFromWindowsISO.DisbledDown(False)
GetDllFromWindowsISO.DisbledUp(True)
GetDllFromWindowsISO.mount = True
isoPath.append(GetDllFromWindowsISO.isoPath.get()) # 将记录写进数组
write_txt(get_home() + "/.config/deepin-wine-runner/ISOPath.json", str(json.dumps(ListToDictionary(isoPath)))) # 将历史记录的数组转换为字典并写入
GetDllFromWindowsISO.isoPath['value'] = isoPath
def UmountDisk():
os.system("pkexec umount /tmp/wine-runner-getdll")
GetDllFromWindowsISO.dllList.configure(state=tk.NORMAL)
try:
shutil.rmtree("/tmp/wine-runner-getdll")
except:
traceback.print_exc()
tkinter.messagebox.showerror(title="错误", message=f"关闭/卸载镜像失败,报错如下:\n{traceback.format_exc()}")
return
GetDllFromWindowsISO.DisbledDown(True)
GetDllFromWindowsISO.DisbledUp(False)
GetDllFromWindowsISO.mount = False
def CopyDll():
for i in GetDllFromWindowsISO.dllList.curselection():
choose = GetDllFromWindowsISO.dllList.get(i)
if os.path.exists(f"{GetDllFromWindowsISO.wineBottonPath}/drive_c/windows/system32/{choose}"):
if not tkinter.messagebox.askyesno(title="提示", message=f"DLL {choose} 已经存在,是否覆盖?"):
continue
print(i)
try:
shutil.copy(f"/tmp/wine-runner-getdll/i386/{choose[:-1]}_", f"{GetDllFromWindowsISO.wineBottonPath}/drive_c/windows/system32/{choose}")
tkinter.messagebox.showinfo(title="提示", message="提取成功!")
except:
traceback.print_exc()
tkinter.messagebox.showerror(title="错误", message=traceback.format_exc())
class ProgramSetting():
wineBottonA = None
wineDebug = None
defultWine = None
defultBotton = None
terminalOpen = None
wineOption = None
#wineBottonDifferent = None
centerWindow = None
def ShowWindow():
message = tk.Toplevel()
ProgramSetting.wineBottonA = tk.StringVar()
ProgramSetting.wineDebug = tk.IntVar()
ProgramSetting.wineDebug.set(int(setting["Debug"]))
ProgramSetting.defultWine = tk.StringVar()
ttk.Label(message, text="选择 Wine 容器版本:").grid(row=0, column=0, sticky=tk.W)
ttk.OptionMenu(message, ProgramSetting.wineBottonA, setting["Architecture"], "Auto", "win32", "win64").grid(row=0, column=1)
ttk.Label(message, text="wine DEBUG 信息输出:").grid(row=1, column=0, sticky=tk.W)
ttk.Checkbutton(message, text="开启 DEBUG 输出", variable=ProgramSetting.wineDebug).grid(row=1, column=1)
ttk.Label(message, text="默认 Wine:").grid(row=2, column=0, sticky=tk.W)
ttk.OptionMenu(message, ProgramSetting.defultWine, setting["DefultWine"], *list(wine)).grid(row=2, column=1) # 创建选择框控件
ttk.Label(message, text="默认 Wine 容器:").grid(row=3, column=0, sticky=tk.W)
ProgramSetting.defultBotton = tk.StringVar()
ProgramSetting.defultBotton.set(setting["DefultBotton"])
ttk.Entry(message, width=30, text=setting["DefultBotton"], textvariable=ProgramSetting.defultBotton).grid(row=3, column=1)
ttk.Button(message, text="浏览", command=ProgramSetting.Browser).grid(row=3, column=2)
ProgramSetting.terminalOpen = tk.IntVar()
ProgramSetting.terminalOpen.set(setting["TerminalOpen"])
ttk.Label(message, text="使用终端打开:").grid(row=4, column=0)
ttk.Checkbutton(message, text="使用终端打开(deepin 终端)", variable=ProgramSetting.terminalOpen).grid(row=4, column=1, columnspan=2)
ttk.Label(message, text="自定义 wine 参数:").grid(row=5, column=0)
ProgramSetting.wineOption = tk.StringVar()
ProgramSetting.wineOption.set(setting["WineOption"])
ProgramSetting.centerWindow = tk.IntVar()
ProgramSetting.centerWindow.set(setting["CenterWindow"])
ttk.Label(message, text="窗口居中设置:").grid(row=6, column=0)
ttk.Checkbutton(message, text="开启窗口在主显示器居中的选项", variable=ProgramSetting.centerWindow).grid(row=6, column=1)
#ttk.Label(message, text="容器创建规则:").grid(row=6, column=0)
#ProgramSetting.wineBottonDifferent = tk.IntVar()
#ProgramSetting.wineBottonDifferent.set(setting["WineBottonDifferent"])
#ttk.Checkbutton(message, text="为每一个可执行文件创建单独的容器(如果勾选的话,上面默认 Wine 容器选项将会指定这些产生的 Wine 容器默认存放目录)", variable=ProgramSetting.wineBottonDifferent)
ttk.Entry(message, width=40, textvariable=ProgramSetting.wineOption).grid(row=5, column=1, columnspan=2)
ttk.Button(message, text="保存", command=ProgramSetting.Save).grid(row=7, column=0, columnspan=3, sticky=tk.E)
# 设置
message.title(f"设置 wine 运行器 {version}")
# 显示
message.mainloop()
def Browser():
path = tkinter.filedialog.askdirectory(title="选择 Wine 容器", initialdir=json.loads(readtxt(get_home() + "/.config/deepin-wine-runner/WineBotton.json"))["path"])
if path == "" or path == None or path == "()" or path == ():
return
ProgramSetting.defultBotton.set(path)
def Save():
# 写入容器位数设置
setting["Architecture"] = ProgramSetting.wineBottonA.get()
setting["Debug"] = bool(ProgramSetting.wineDebug.get())
setting["DefultWine"] = ProgramSetting.defultWine.get()
setting["DefultBotton"] = ProgramSetting.defultBotton.get()
setting["TerminalOpen"] = bool(ProgramSetting.terminalOpen.get())
setting["WineOption"] = ProgramSetting.wineOption.get()
#setting["WineBottonDifferent"] = bool(ProgramSetting.wineBottonDifferent.get())
setting["CenterWindow"] = bool(ProgramSetting.centerWindow.get())
try:
write_txt(get_home() + "/.config/deepin-wine-runner/WineSetting.json", json.dumps(setting))
except:
traceback.print_exc()
tkinter.messagebox.showerror(title="错误", message=traceback.format_exc())
return
tkinter.messagebox.showinfo(title="提示", message="保存完毕!")
###########################
# 加载配置
###########################
defultProgramList = {
"Architecture": "Auto",
"Debug": True,
"DefultWine": "deepin-wine6 stable",
"DefultBotton" : get_home() + "/.wine",
"TerminalOpen": False,
"WineOption": "",
"WineBottonDifferent": False,
"CenterWindow": False
}
if not os.path.exists(get_home() + "/.config/deepin-wine-runner"): # 如果没有配置文件夹
os.mkdir(get_home() + "/.config/deepin-wine-runner") # 创建配置文件夹
if not os.path.exists(get_home() + "/.config/deepin-wine-runner/ShellHistory.json"): # 如果没有配置文件
write_txt(get_home() + "/.config/deepin-wine-runner/ShellHistory.json", json.dumps({})) # 创建配置文件
if not os.path.exists(get_home() + "/.config/deepin-wine-runner/FindExeHistory.json"): # 如果没有配置文件
write_txt(get_home() + "/.config/deepin-wine-runner/FindExeHistory.json", json.dumps({})) # 创建配置文件
if not os.path.exists(get_home() + "/.config/deepin-wine-runner/WineBottonHistory.json"): # 如果没有配置文件
write_txt(get_home() + "/.config/deepin-wine-runner/WineBottonHistory.json", json.dumps({})) # 创建配置文件
if not os.path.exists(get_home() + "/.config/deepin-wine-runner/ISOPath.json"): # 如果没有配置文件
write_txt(get_home() + "/.config/deepin-wine-runner/ISOPath.json", json.dumps({})) # 写入(创建)一个配置文件
if not os.path.exists(get_home() + "/.config/deepin-wine-runner/ISOPathFound.json"): # 如果没有配置文件
write_txt(get_home() + "/.config/deepin-wine-runner/ISOPathFound.json", json.dumps({})) # 写入(创建)一个配置文件
if not os.path.exists(get_home() + "/.config/deepin-wine-runner/FindExe.json"): # 如果没有配置文件
write_txt(get_home() + "/.config/deepin-wine-runner/FindExe.json", json.dumps({"path": "~"})) # 写入(创建)一个配置文件
if not os.path.exists(get_home() + "/.config/deepin-wine-runner/FindISO.json"): # 如果没有配置文件
write_txt(get_home() + "/.config/deepin-wine-runner/FindISO.json", json.dumps({"path": "~"})) # 写入(创建)一个配置文件
if not os.path.exists(get_home() + "/.config/deepin-wine-runner/WineBotton.json"): # 如果没有配置文件
write_txt(get_home() + "/.config/deepin-wine-runner/WineBotton.json", json.dumps({"path": "~/.deepinwine"})) # 写入(创建)一个配置文件
if not os.path.exists(get_home() + "/.config/deepin-wine-runner/WineSetting.json"): # 如果没有配置文件
write_txt(get_home() + "/.config/deepin-wine-runner/WineSetting.json", json.dumps(defultProgramList)) # 写入(创建)一个配置文件
###########################
# 设置变量
###########################
# 如果要添加其他 wine,请在字典添加其名称和执行路径
try:
wine = {"deepin-wine": "deepin-wine", "deepin-wine5": "deepin-wine5", "wine": "wine", "wine64": "wine64", "deepin-wine5 stable": "deepin-wine5-stable", "deepin-wine6 stable": "deepin-wine6-stable", "spark-wine7-devel": "spark-wine7-devel", "ukylin-wine": "ukylin-wine"}
shellHistory = list(json.loads(readtxt(get_home() + "/.config/deepin-wine-runner/ShellHistory.json")).values())
findExeHistory = list(json.loads(readtxt(get_home() + "/.config/deepin-wine-runner/FindExeHistory.json")).values())
wineBottonHistory = list(json.loads(readtxt(get_home() + "/.config/deepin-wine-runner/WineBottonHistory.json")).values())
isoPath = list(json.loads(readtxt(get_home() + "/.config/deepin-wine-runner/ISOPath.json")).values())
isoPathFound = list(json.loads(readtxt(get_home() + "/.config/deepin-wine-runner/ISOPathFound.json")).values())
setting = json.loads(readtxt(get_home() + "/.config/deepin-wine-runner/WineSetting.json"))
change = False
for i in ["Architecture", "Debug", "DefultWine", "DefultBotton", "TerminalOpen", "WineOption", "WineBottonDifferent", "CenterWindow"]:
if not i in setting:
change = True
setting[i] = defultProgramList[i]
if change:
write_txt(get_home() + "/.config/deepin-wine-runner/WineSetting.json", json.dumps(setting))
except:
root = tk.Tk()
root.withdraw()
tkinter.messagebox.showerror(title="错误", message="无法读取配置,无法继续")
sys.exit(1)
###########################
# 程序信息
###########################
programPath = os.path.split(os.path.realpath(__file__))[0] # 返回 string
iconPath = "{}/icon.png".format(programPath)
programUrl = "https://gitee.com/gfdgd-xi/deep-wine-runner\nhttps://github.com/gfdgd-xi/deep-wine-runner\nhttps://www.gitlink.org.cn/gfdgd_xi/deep-wine-runner"
information = json.loads(readtxt(f"{programPath}/information.json"))
version = information["Version"]
goodRunSystem = "Linux"
about = '''一个基于 Python3 的 tkinter 制作的 wine 运行器
版本:{}
适用平台:{}
tkinter 版本:{}
程序官网:{}
©2020-{} gfdgd xi'''.format(version, goodRunSystem, tk.TkVersion, programUrl, time.strftime("%Y"))
tips = '''提示:
1、使用终端运行该程序,可以看到 wine 以及程序本身的提示和报错;
2、wine 32 位和 64 位的容器互不兼容;
3、所有的 wine 和 winetricks 均需要自行安装(可以从 菜单栏=>程序 里面进行安装)
4、本程序支持带参数运行 wine 程序(之前版本也可以),只需要按以下格式即可:
exe路径\' 参数 \'
即可(单引号需要输入)
5、wine 容器如果没有指定,则会默认为 ~/.wine'''
updateThingsString = '''※1、添加 @delsin 和 @神末shenmo 建议的 postrm 脚本
2、将 pip 由阿里源改为华为源,提升下载速度
3、优化多屏窗口居中问题,并设置居中选项为选开防止错误
4、修复 1.6.0 程序无法保存设置的问题
'''
title = "wine 运行器 {}".format(version)
updateTime = "2022年07月11日"
updateThings = "{} 更新内容:\n{}\n更新时间:{}".format(version, updateThingsString, updateTime, time.strftime("%Y"))
thankText = ""
for i in information["Thank"]:
thankText += f"{i}\n"
###########################
# 窗口创建
###########################
# 读取主题
try:
theme = not ("dark" in readtxt(get_home() + "/.gtkrc-2.0") and "gtk-theme-name=" in readtxt(get_home() + "/.gtkrc-2.0"))
except:
print("主题读取错误,默认使用浅色主题")
theme = True
if theme:
style = ttkbootstrap.Style(theme="litera")
win = style.master # 创建窗口
else:
style = ttkbootstrap.Style(theme="darkly")
win = style.master # 创建窗口
win.title(title) # 设置标题
#root.geometry("1275x900")
# 设置变量以修改和获取值项
o1_text = tk.StringVar()
combobox1 = tk.StringVar()
o1_text.set("deepin-wine6 stable")
frame_up = ttk.Frame(win)
frame_left = tk.Frame(frame_up)#快速启动区
frame_left.config(bd=30)
#
frame_left_1 = ttk.Frame(frame_left)#左侧标题
left_title = ttk.Label(frame_left_1,text="快速启动")
left_title.config(font=("幼圆",24))
left_title.pack(anchor="w")
frame_left_1.grid(row=0,sticky="w" + "e")
#
frame_left_2 = ttk.Frame(frame_left)#容器路径
##
label_l_1 = ttk.Label(frame_left_2,text="请选择容器的路径:")
label_l_1.config(font=("幼圆",16))
label_l_1.grid(row=0,column=0,sticky='w')
##
e1 = ttk.Combobox(frame_left_2, width=65)
e1.grid(row=1,column=0)
##
button1 = tk.Button(frame_left_2,text="浏览", command=liulanbutton)
button1.config(font=("幼圆",12),padx=20,pady=3)
button1.grid(row=1,column=1)
##
frame_left_2.grid(row=1)
#
frame_left_3 = ttk.Frame(frame_left)#程序路径
label_l_2 = ttk.Label(frame_left_3,text="请选择待执行程序:")
label_l_2.config(font=("幼圆",16))
label_l_2.grid(row=0,column=0,sticky='w')
##
e2 = ttk.Combobox(frame_left_3, width=65)
e2.grid(row=1,column=0)
##
button2 = tk.Button(frame_left_3,text="浏览", command=liulanexebutton)
button2.config(font=("幼圆",12),padx=20,pady=3)
button2.grid(row=1,column=1)
##
frame_left_3.grid(row=2)
#
frame_left_4 = ttk.Frame(frame_left)#wine的版本
##
label_l_3 = ttk.Label(frame_left_4,text="请选择wine的版本")
label_l_3.config(font=("幼圆",16))
label_l_3.grid(row=0,column=0,sticky='w')
##
o1 = ttk.OptionMenu(frame_left_4, o1_text, setting["DefultWine"], *list(wine))
o1.grid(row=1,column=0)
##
label_l_4 = ttk.Label(frame_left_4,text=" "*4)#占位用字符串
label_l_4.grid(row=1,column=1)
##
button3 = tk.Button(frame_left_4,text="运行程序", command=runexebutton)
button3.config(font=("幼圆",12),padx=21,pady=3)
button3.grid(row=1,column=2)
##
label_l_5 = ttk.Label(frame_left_4,text=" "*13)#占位用字符串
label_l_5.grid(row=1,column=3)
##
killProgram = tk.Button(frame_left_4,text="终止程序", command=KillProgram)
killProgram.config(font=("幼圆",12),padx=21,pady=3)
killProgram.grid(row=1,column=4)
##
frame_left_4.grid(row=3)
#
frame_left.grid(row=0,column=0)#第一行第一列
frame_right = tk.Frame(frame_up)#高级配置区
frame_right.config(bd=30)
#
frame_right_1 = ttk.Frame(frame_right)
right_title = ttk.Label(frame_right_1,text="高级功能")
right_title.config(font=("幼圆",24))
right_title.pack(anchor="w")
frame_right_1.grid(row=0,sticky="w" + "e")
#
frame_right_2 = tk.Frame(frame_right)
##
label_r_1 = ttk.Label(frame_right_2,text="创建快捷方式(Desktop文件):")
label_r_1.config(font=("幼圆",16))
label_r_1.grid(row=0,column=0)
##
frame_right_2.grid(row=1,sticky='w')
#
frame_right_3 = tk.Frame(frame_right)
##
label_r_2 = ttk.Label(frame_right_3,text="名称:")
label_r_2.config(font=("幼圆",14))
label_r_2.grid(row=0,column=0)
##
combobox1 = ttk.Combobox(frame_right_3,width=20)
combobox1.grid(row=0,column=1)
##
empty1 = ttk.Label(frame_right_3,text=" "*5)
empty1.grid(row=0,column=2)
##
button5 = tk.Button(frame_right_3,text="创建到桌面", command=make_desktop_on_desktop)
button5.config(font=("幼圆",12),padx=20,pady=3)
button5.grid(row=0,column=3)
##
empty2 = ttk.Label(frame_right_3,text=" "*5)
empty2.grid(row=0,column=4)
##
saveDesktopFileOnLauncher = tk.Button(frame_right_3,text="创建到开始菜单", command=make_desktop_on_launcher)
saveDesktopFileOnLauncher.config(font=("幼圆",12),padx=20,pady=3)
saveDesktopFileOnLauncher.grid(row=0,column=5)
##
frame_right_3.grid(row=2,sticky='w')
#
frame_right_4 = ttk.Frame(frame_right)
##
label_r_2 = ttk.Label(frame_right_4,text="管理该程序:")
label_r_2.config(font=("幼圆",16))
label_r_2.grid(row=0,column=0)
##
frame_right_4.grid(row=3,sticky='w')
#
frame_right_5 = ttk.Frame(frame_right)
##
uninstallProgram = tk.Button(frame_right_5,text="卸载程序", command=UninstallProgram)
uninstallProgram.config(font=("幼圆",12),padx=20,pady=3)
uninstallProgram.grid(column=0)
##
empty3 = ttk.Label(frame_right_5,text=" "*5)
empty3.grid(row=0,column=1)
##
getProgramIcon = tk.Button(frame_right_5,text="提取图标", command=lambda: threading.Thread(target=RunWineProgram, args=[f"{programPath}/BeCyIconGrabber.exe"]).start())
getProgramIcon.config(font=("幼圆",12),padx=20,pady=3)
getProgramIcon.grid(row=0,column=2)
##
empty6 = ttk.Label(frame_right_5,text=" "*5)
empty6.grid(row=0,column=3)
##
trasButton = tk.Button(frame_right_5,text="窗口透明度工具", command=lambda: threading.Thread(target=RunWineProgram, args=[programPath + "/窗体透明度设置工具.exe"]).start())
trasButton.config(font=("幼圆",12),padx=20,pady=3)
trasButton.grid(row=0,column=4)
##
frame_right_5.grid(row=4,sticky='w')
#
frame_right_6 = ttk.Frame(frame_right)
##
label_r_3 = ttk.Label(frame_right_6,text="管理该wine")
label_r_3.config(font=("幼圆",16))
label_r_3.grid(row=0,column=0)
##
frame_right_6.grid(row=5,sticky='w')
#
frame_right_7 = ttk.Frame(frame_right)
##
wineConfig = tk.Button(frame_right_7,text="配置容器", command=ConfigWineBotton)
wineConfig.config(font=("幼圆",12),padx=20,pady=3)
wineConfig.grid(row=0,column=0)
##
empty4 = ttk.Label(frame_right_7,text=" "*5)
empty4.grid(row=0,column=1)
##
button_r_6 = tk.Button(frame_right_7,text="安装字体", command=OpenWineFontPath)
button_r_6.config(font=("幼圆",12),padx=20,pady=3)
button_r_6.grid(row=0,column=2)
##
empty5 = ttk.Label(frame_right_7,text=" "*5)
empty5.grid(row=0,column=3)
##
sparkWineSetting = tk.Button(frame_right_7,text="星火wine设置", command=lambda: threading.Thread(target=os.system, args=["/opt/durapps/spark-dwine-helper/spark-dwine-helper-settings/settings.sh"]).start())
sparkWineSetting.config(font=("幼圆",12),padx=20,pady=3)
sparkWineSetting.grid(row=0,column=4)
##
frame_right_7.grid(row=6,sticky='w')
#
frame_right.grid(row=0,column=1,sticky='n')#第一行第二列
frame_up.grid(row=0,sticky='w')
frame_down = tk.Frame(win,bd=30)
returnText = tk.Text(frame_down,width=120, height=15)
returnText.insert("end", "此可以查看到 Wine 应用安装时的程序返回值")
returnText.config(state=tk.DISABLED)
returnText.grid(row=0,column=0,sticky='e'+'w')
frame_down.grid(row=1,sticky='w')
menu = tk.Menu(win, background="white") # 设置菜单栏
programmenu = tk.Menu(menu, tearoff=0, background="white") # 设置“程序”菜单栏
menu.add_cascade(label="程序", menu=programmenu)
programmenu.add_command(label="安装 wine", command=InstallWine)
programmenu.add_separator() # 设置分界线
programmenu.add_command(label="设置程序", command=ProgramSetting.ShowWindow)
programmenu.add_command(label="清空软件历史记录", command=CleanProgramHistory)
programmenu.add_separator() # 设置分界线
programmenu.add_command(label="退出程序", command=win.quit) # 设置“退出程序”项
wineOption = tk.Menu(menu, tearoff=0, background="white") # 设置“Wine”菜单栏
menu.add_cascade(label="Wine", menu=wineOption)
wineOption.add_command(label="打开 Wine 容器目录", command=OpenWineBotton)
wineOption.add_command(label="安装常见字体", command=InstallWineFont)
wineOption.add_command(label="安装自定义字体", command=OpenWineFontPath)
wineOption.add_command(label="删除选择的 Wine 容器", command=DeleteWineBotton)
wineOption.add_separator()
wineOption.add_command(label="打包 wine 应用", command=BuildExeDeb)
wineOption.add_command(label="使用官方 Wine 适配活动的脚本进行打包(测试只支持UOS)", command=UOSPackageScript)
wineOption.add_separator()
wineOption.add_command(label="从镜像获取DLL(只支持Windows XP、Windows Server 2003官方安装镜像)", command=GetDllFromWindowsISO.ShowWindow)
wineOption.add_separator()
wineInstall = tk.Menu()
wineOption.add_cascade(label="在指定 Wine、容器安装组件", menu=wineInstall)
wineInstall.add_command(label="在指定wine、指定容器安装 .net framework", command=lambda: threading.Thread(target=InstallNetFramework).start())
wineInstall.add_command(label="在指定wine、指定容器安装 Visual Studio C++", command=lambda: threading.Thread(target=InstallVisualStudioCPlusPlus).start())
wineInstall.add_command(label="在指定wine、指定容器安装 MSXML", command=lambda: threading.Thread(target=InstallMSXML).start())
wineInstall.add_command(label="在指定wine、指定容器安装 gecko", command=lambda: threading.Thread(target=InstallMonoGecko, args=["gecko"]).start())
wineInstall.add_command(label="在指定wine、指定容器安装 mono", command=lambda: threading.Thread(target=InstallMonoGecko, args=["mono"]).start())
wineInstall.add_command(label="在指定wine、指定容器安装其它运行库", command=lambda: threading.Thread(target=InstallOther).start())
wineDefultMenu = tk.Menu()
wineOption.add_cascade(label="在指定 Wine、容器运行基础应用", menu=wineDefultMenu)
wineDefultMenu.add_command(label="打开指定wine、指定容器的控制面板", command=lambda: threading.Thread(target=RunWineProgram, args=["control"]).start())
wineDefultMenu.add_command(label="打开指定wine、指定容器的浏览器", command=lambda: threading.Thread(target=RunWineProgram, args=["iexplore' 'https://www.deepin.org"]).start())
wineDefultMenu.add_command(label="打开指定wine、指定容器的注册表", command=lambda: threading.Thread(target=RunWineProgram, args=["regedit"]).start())
wineDefultMenu.add_command(label="打开指定wine、指定容器的任务管理器", command=lambda: threading.Thread(target=RunWineProgram, args=["taskmgr"]).start())
wineDefultMenu.add_command(label="打开指定wine、指定容器的资源管理器", command=lambda: threading.Thread(target=RunWineProgram, args=["explorer"]).start())
wineDefultMenu.add_command(label="打开指定wine、指定容器的关于 wine", command=lambda: threading.Thread(target=RunWineProgram, args=["winver"]).start())
wineOption.add_separator()
wineOption.add_command(label="设置 run_v3.sh 的文管为 Deepin 默认文管", command=SetDeepinFileDialogDeepin)
wineOption.add_command(label="设置 run_v3.sh 的文管为 Wine 默认文管", command=SetDeepinFileDialogDefult)
wineOption.add_command(label="重新安装 deepin-wine-helper", command=SetDeepinFileDialogRecovery)
wineOption.add_separator()
wineOption.add_command(label="使用winetricks打开指定容器", command=lambda: threading.Thread(target=RunWinetricks).start())
wineOption.add_separator()
opengl = tk.Menu()
opengl.add_command(label="开启 opengl", command=lambda: threading.Thread(target=RunWineProgram, args=[f"regedit.exe' /s '{programPath}/EnabledOpengl.reg"]).start())
opengl.add_command(label="禁用 opengl", command=lambda: threading.Thread(target=RunWineProgram, args=[f"regedit.exe' /s '{programPath}/DisabledOpengl.reg"]).start())
wineOption.add_cascade(label="启用/禁用 opengl", menu=opengl)
winbind = tk.Menu()
winbind.add_command(label="安装 winbind", command=lambda: os.system(f"'{programPath}/launch.sh' deepin-terminal -C 'pkexec apt install winbind -y' --keep-open"))
winbind.add_command(label="卸载 winbind", command=lambda: os.system(f"'{programPath}/launch.sh' deepin-terminal -C 'pkexec apt purge winbind -y' --keep-open"))
wineOption.add_cascade(label="安装/卸载 winbind", menu=winbind)
virtualMachine = tk.Menu(menu, tearoff=0, background="white")
menu.add_cascade(label="虚拟机", menu=virtualMachine)
virtualMachine.add_command(label="使用 Virtualbox 虚拟机运行 Windows 应用", command=RunVM)
safeWebsize = tk.Menu(menu, tearoff=0, background="white")
menu.add_cascade(label="云沙箱", menu=safeWebsize)
safeWebsize.add_command(label="360 沙箱云", command=lambda: webbrowser.open_new_tab("https://ata.360.net/"))
safeWebsize.add_command(label="微步云沙箱", command=lambda: webbrowser.open_new_tab("https://s.threatbook.cn/"))
safeWebsize.add_command(label="VIRUSTOTAL", command=lambda: webbrowser.open_new_tab("https://www.virustotal.com/"))
help = tk.Menu(menu, tearoff=0, background="white") # 设置“帮助”菜单栏
menu.add_cascade(label="帮助", menu=help)
help.add_command(label="程序官网", command=OpenProgramURL) # 设置“程序官网”项
help.add_separator()
help.add_command(label="小提示", command=helps) # 设置“小提示”项
help.add_command(label="更新内容", command=UpdateThings) # 设置“更新内容”项
help.add_command(label="谢明名单", command=ThankWindow)
help.add_separator()
help.add_command(label="更新这个程序", command=UpdateWindow.ShowWindow)
help.add_command(label="反馈这个程序的建议和问题", command=WineRunnerBugUpload)
help.add_command(label="关于这个程序", command=about_this_program) # 设置“关于这个程序”项
help.add_separator()
moreProgram = tk.Menu(menu, tearoff=0, background="white")
help.add_cascade(label="更多生态适配应用", menu=moreProgram)
moreProgram.add_command(label="运行 Android 应用:UEngine 运行器", command=lambda: webbrowser.open_new_tab("https://gitee.com/gfdgd-xi/uengine-runner"))
# 设置窗口
win.iconphoto(False, tk.PhotoImage(file=iconPath))
#win.config(bg="white")
win.config(menu=menu)
# 设置控件
e1.set(setting["DefultBotton"])
if len(sys.argv) > 1 and sys.argv[1]:
e2.set(sys.argv[1])
menu.configure(activebackground="dodgerblue")
programmenu.configure(activebackground="dodgerblue")
wineOption.configure(activebackground="dodgerblue")
wineDefultMenu.configure(activebackground="dodgerblue")
wineInstall.configure(activebackground="dodgerblue")
opengl.configure(activebackground="dodgerblue")
winbind.configure(activebackground="dodgerblue")
virtualMachine.configure(activebackground="dodgerblue")
safeWebsize.configure(activebackground="dodgerblue")
moreProgram.configure(activebackground="dodgerblue")
help.configure(activebackground="dodgerblue")
e1['value'] = findExeHistory
e2['value'] = wineBottonHistory
combobox1['value'] = shellHistory
returnText.insert("end", "此可以查看到 Wine 应用安装时的程序返回值")
returnText.config(state=tk.DISABLED)
if not os.path.exists("/opt/durapps/spark-dwine-helper/spark-dwine-helper-settings/settings.sh"):
sparkWineSetting.config(state=tk.DISABLED)
# 启动窗口
if setting["CenterWindow"]:
try:
# 窗口居中(如果设置开启)
win.update()
# 获取主显示器分辨率
for i in GetScreenSize():
if i[4]:
win.geometry(f"{win.winfo_width()}x{win.winfo_height()}+{i[2] + (i[0] // 2 - win.winfo_width() // 2)}+{i[3] + (i[1] // 2 - win.winfo_height() // 2)}")
except:
print("设置居中错误,忽略")
# 显示窗口
win.mainloop()
Python
1
https://gitee.com/gfdgd-xi/deep-wine-runner.git
git@gitee.com:gfdgd-xi/deep-wine-runner.git
gfdgd-xi
deep-wine-runner
Wine 运行器
main

搜索帮助