mirror of
https://gitee.com/gfdgd-xi/deep-wine-runner
synced 2025-12-15 03:22:04 +08:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9cc549527d | |||
| 43e473ad39 | |||
| d78916f4b0 | |||
| bf370e9a91 | |||
| 84f71c2043 | |||
| e5231d7846 | |||
| b653bcbb80 | |||
| ad9deaed81 | |||
| 1b9e106d2a | |||
| c51cf18f4c | |||
| 4217f58c2c |
BIN
GetEXEVersion.exe
Executable file
BIN
GetEXEVersion.exe
Executable file
Binary file not shown.
29
IconList.json
Normal file
29
IconList.json
Normal file
@@ -0,0 +1,29 @@
|
||||
[
|
||||
[
|
||||
["QQ", "wineBottonPath/drive_c/Program Files/Tencent/QQ/Bin/QQ.exe"],
|
||||
["QQ", "wineBottonPath/drive_c/Program Files (x86)/Tencent/QQ/Bin/QQ.exe"],
|
||||
["TIM", "wineBottonPath/drive_c/Program Files/Tencent/TIM/Bin/TIM.exe"],
|
||||
["TIM", "wineBottonPath/drive_c/Program Files (x86)/Tencent/TIM/Bin/TIM.exe"]
|
||||
],
|
||||
[
|
||||
["cmd", "cmd"],
|
||||
["cmd", "cmd.exe"],
|
||||
["cmd", "wineBottonPath/drive_c/windows/system32/cmd.exe"],
|
||||
["Internet Explorer", "iexplore"],
|
||||
["Internet Explorer", "iexplore.exe"],
|
||||
["Internet Explorer", "wineBottonPath/drive_c/Program Files/Internet Explorer/iexplore.exe"],
|
||||
["Internet Explorer", "wineBottonPath/drive_c/Program Files (x86)/Internet Explorer/iexplore.exe"],
|
||||
["微信", "wineBottonPath/drive_c/Program Files/Tencent/WeChat/WeChat.exe"],
|
||||
["微信", "wineBottonPath/drive_c/Program Files (x86)/Tencent/WeChat/WeChat.exe"],
|
||||
["UltraISO", "wineBottonPath/drive_c/Program Files/UltraISO/UltraISO.exe"],
|
||||
["UltraISO", "wineBottonPath/drive_c/Program Files (x86)/UltraISO/UltraISO.exe"],
|
||||
["迅雷", "wineBottonPath/drive_c/Program Files/Thunder Network/MiniThunder/Bin/ThunderMini.exe"],
|
||||
["迅雷", "wineBottonPath/drive_c/Program Files (x86)/Thunder Network/MiniThunder/Bin/ThunderMini.exe"],
|
||||
["Microsoft Office Word", "wineBottonPath/drive_c/Program Files/Microsoft Office/Office12/WINWORD.EXE"],
|
||||
["Microsoft Office Word", "wineBottonPath/drive_c/Program Files (x86)/Microsoft Office/Office12/WINWORD.EXE"],
|
||||
["腾讯会议", "wineBottonPath/drive_c/Program Files/Tencent/WeMeet/wemeetapp.exe"],
|
||||
["腾讯会议", "wineBottonPath/drive_c/Program Files (x86)/Tencent/WeMeet/wemeetapp.exe"],
|
||||
["腾讯课堂", "wineBottonPath/drive_c/Program Files/Tencent/EDU/bin/TXEDU.exe"],
|
||||
["腾讯课堂", "wineBottonPath/drive_c/Program Files (x86)/Tencent/EDU/bin/TXEDU.exe"]
|
||||
]
|
||||
]
|
||||
4
Makefile
4
Makefile
@@ -16,6 +16,10 @@ build:
|
||||
cp -rv AllInstall.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv kill.sh deb/opt/apps/deepin-wine-runner
|
||||
cp -rv InstallWineOnDeepin23Alpha.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv wrestool deb/opt/apps/deepin-wine-runner
|
||||
cp -rv deepin-wine-easy-packager.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv IconList.json deb/opt/apps/deepin-wine-runner
|
||||
cp -rv GetEXEVersion.exe deb/opt/apps/deepin-wine-runner
|
||||
echo "[]" > deb/opt/apps/deepin-wine-runner/wine/winelist.json
|
||||
rm -rfv deb/opt/apps/deepin-wine-runner/wine/winelist.json
|
||||
cp -rv req deb/opt/apps/deepin-wine-runner
|
||||
|
||||
@@ -11,7 +11,6 @@ env WINEPREFIX=容器路径 wine(wine的路径) 可执行文件路径
|
||||
```
|
||||
让你可以简易方便的使用 wine
|
||||
是使用 Python3 的 PyQt5 构建的
|
||||
(自己美术功底太差,图标只能在网络上找了)
|
||||
(测试平台:deepin 20.7.1;UOS 家庭版 21.3.1;Ubuntu 22.04;Ubuntu 20.04;UOS 专业版 1050;openkylin)
|
||||

|
||||
而打包器可以方便的把您的 wine 容器打包成 deb 包供他人使用,程序创建的 deb 构建临时文件夹目录树如下:
|
||||
@@ -104,6 +103,9 @@ desktop文件中StartupWMClass字段。用于让桌面组件将窗口类名与de
|
||||

|
||||
|
||||
## 更新日志
|
||||
### 2.5.0.1(2022年11月25日)
|
||||
**※1、修复已知问题**
|
||||
|
||||
### 2.5.0(2022年11月25日)
|
||||
**※1、容器自动配置脚本 GUI 查看介绍使用 QWebEngineWidget,支持图片(非强制依赖,只做推荐);**
|
||||
**※2、不基于生态适配活动脚本打包器跟进 arm 架构 2022年11月11日的 Wine 微信打包方式;**
|
||||
|
||||
BIN
Wine运行器和Wine打包器傻瓜式使用教程(小白专用)20221126-V2.pdf
Normal file
BIN
Wine运行器和Wine打包器傻瓜式使用教程(小白专用)20221126-V2.pdf
Normal file
Binary file not shown.
@@ -1,5 +1,5 @@
|
||||
Package: spark-deepin-wine-runner
|
||||
Version: 2.5.0
|
||||
Version: 2.6.0~alpha1
|
||||
Maintainer: gfdgd xi <3025613752@qq.com>, 为什么您不喜欢熊出没和阿布呢
|
||||
Homepage: https://gitee.com/gfdgd-xi/deep-wine-runner, https://github.com/gfdgd-xi/deep-wine-runner, https://gitlink.org.cn/gfdgd_xi/deep-wine-runner
|
||||
Architecture: all
|
||||
|
||||
616
deepin-wine-easy-packager.py
Normal file
616
deepin-wine-easy-packager.py
Normal file
@@ -0,0 +1,616 @@
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import time
|
||||
import random
|
||||
import xpinyin
|
||||
import traceback
|
||||
import subprocess
|
||||
import PyQt5.QtGui as QtGui
|
||||
import PyQt5.QtCore as QtCore
|
||||
import PyQt5.QtWidgets as QtWidgets
|
||||
|
||||
def ShowText(text: str):
|
||||
if text.replace(" ", "").replace("\n", "") == "":
|
||||
return
|
||||
logText.append(text.replace("\n", ""))
|
||||
|
||||
def ErrorMessage(text: str):
|
||||
QtWidgets.QMessageBox.critical(window, "错误", text)
|
||||
|
||||
def InformationMessage(text: str):
|
||||
QtWidgets.QMessageBox.information(window, "提示", text)
|
||||
|
||||
questionChoose = False
|
||||
questionStatus = False
|
||||
def QuestionMessage(text: str):
|
||||
global questionChoose
|
||||
global questionStatus
|
||||
# 清零
|
||||
questionChoose = False
|
||||
questionStatus = False
|
||||
if QtWidgets.QMessageBox.question(window, "提示", text) == QtWidgets.QMessageBox.Yes:
|
||||
questionChoose = True
|
||||
print(questionChoose)
|
||||
questionStatus = True
|
||||
return
|
||||
questionChoose = False
|
||||
questionStatus = True
|
||||
|
||||
|
||||
def DisbledAndEnabledAll(choose: bool):
|
||||
exePath.setDisabled(choose)
|
||||
browserExeButton.setDisabled(choose)
|
||||
buildButton.setDisabled(choose)
|
||||
|
||||
# 获取用户主目录
|
||||
def get_home():
|
||||
return os.path.expanduser('~')
|
||||
|
||||
def get_desktop_path():
|
||||
try:
|
||||
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 # 返回目录
|
||||
except:
|
||||
traceback.print_exc()
|
||||
return get_home()
|
||||
|
||||
def CleanPressCompleteDownloadState(option):
|
||||
global pressCompleteDownload
|
||||
pressCompleteDownload = False
|
||||
installCmpleteButton.setEnabled(True)
|
||||
|
||||
# 读取 lnk 文件
|
||||
def GetLnkDesktop(path):
|
||||
lnkList = []
|
||||
for i in os.listdir(path):
|
||||
filePath = f"{path}/{i}"
|
||||
if os.path.islink(filePath):
|
||||
# 忽略 link 链接
|
||||
continue
|
||||
if os.path.isdir(filePath):
|
||||
lists = GetLnkDesktop(filePath)
|
||||
for k in lists:
|
||||
lnkList.append(k)
|
||||
continue
|
||||
if os.path.isfile(filePath) and os.path.splitext(filePath)[1] == ".lnk":
|
||||
with open(filePath, "rb") as file:
|
||||
while True:
|
||||
things = file.readline().lower()
|
||||
if things == b"":
|
||||
break
|
||||
print(things[1: -2].split("\x00".encode("gbk")))
|
||||
for k in things[1: -2].split("\x00".encode("gbk")):
|
||||
if "c:".encode("gbk") in k:
|
||||
print(k.decode("gbk"))
|
||||
lnkList.append([filePath, k.decode("gbk")])
|
||||
return lnkList
|
||||
|
||||
def ReplaceText(string: str, lists: list):
|
||||
for i in lists:
|
||||
string = string.replace(i[0], i[1])
|
||||
return string
|
||||
|
||||
control = '''Package: @@@Package@@@
|
||||
Version: @@@Version@@@
|
||||
Architecture: i386
|
||||
Maintainer: @@@Maintainer@@@
|
||||
Depends: @@@Depends@@@
|
||||
Section: non-free/otherosfs
|
||||
Priority: optional
|
||||
Multi-Arch: foreign
|
||||
Installed-Size: @@@Installed-Size@@@
|
||||
Description: @@@Description@@@
|
||||
'''
|
||||
|
||||
info = f'''{{
|
||||
"appid": "@@@Package@@@",
|
||||
"name": "@@@Name@@@",
|
||||
"version": "@@@Version@@@",
|
||||
"arch": ["i386"],
|
||||
"permissions": {{
|
||||
"autostart": false,
|
||||
"notification": false,
|
||||
"trayicon": true,
|
||||
"clipboard": true,
|
||||
"account": false,
|
||||
"bluetooth": false,
|
||||
"camera": true,
|
||||
"audio_record": true,
|
||||
"installed_apps": false
|
||||
}}
|
||||
}}'''
|
||||
|
||||
postrm = f"""#!/bin/bash
|
||||
if [ "$1" = "remove" ] || [ "$1" = "purge" ];then
|
||||
|
||||
echo "清理卸载残留"
|
||||
CONTAINER_NAME="@@@Package@@@"
|
||||
|
||||
if [ -z $CONTAINER_NAME ];then
|
||||
echo "W: 没有指定容器,跳过清理容器。请手动前往 ~/.deepinwine/ 下删除"
|
||||
exit
|
||||
fi
|
||||
|
||||
/opt/deepinwine/tools/kill.sh $CONTAINER_NAME
|
||||
###这里注意,如果没写CONTAINER_NAME,会把QQ杀了
|
||||
|
||||
for username in $(ls /home)
|
||||
do
|
||||
echo /home/$username
|
||||
if [ -d /home/$username/.deepinwine/$CONTAINER_NAME ]
|
||||
then
|
||||
rm -rf /home/$username/.deepinwine/$CONTAINER_NAME
|
||||
fi
|
||||
done
|
||||
else
|
||||
echo "非卸载,跳过清理"
|
||||
fi"""
|
||||
|
||||
runsh = f'''#!/bin/sh
|
||||
|
||||
# Copyright (C) 2016 Deepin, Inc.
|
||||
#
|
||||
# Author: Li LongYu <lilongyu@linuxdeepin.com>
|
||||
# Peng Hao <penghao@linuxdeepin.com>
|
||||
#
|
||||
#
|
||||
# Copyright (C) 2022 The Spark Project
|
||||
#
|
||||
#
|
||||
# Modifier shenmo <shenmo@spark-app.store>
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
#######################函数段。下文调用的额外功能会在此处声明
|
||||
|
||||
Get_Dist_Name()
|
||||
{{
|
||||
if grep -Eqii "Deepin" /etc/issue || grep -Eq "Deepin" /etc/*-release; then
|
||||
DISTRO='Deepin'
|
||||
elif grep -Eqi "UnionTech" /etc/issue || grep -Eq "UnionTech" /etc/*-release; then
|
||||
DISTRO='UniontechOS'
|
||||
else
|
||||
DISTRO='OtherOS'
|
||||
fi
|
||||
}}
|
||||
|
||||
|
||||
####获得发行版名称
|
||||
|
||||
#########################预设值段
|
||||
|
||||
version_gt() {{ test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"; }}
|
||||
####用于比较版本?未实装
|
||||
BOTTLENAME="@@@Package@@@"
|
||||
APPVER="@@@Version@@@"
|
||||
EXEC_PATH="@@@EXEC_PATH@@@"
|
||||
##### 软件在wine中的启动路径
|
||||
START_SHELL_PATH="/opt/deepinwine/tools/spark_run_v4.sh"
|
||||
export MIME_TYPE=""
|
||||
#####没什么用
|
||||
export DEB_PACKAGE_NAME="@@@Package@@@"
|
||||
####这里写包名才能在启动的时候正确找到files.7z,似乎也和杀残留进程有关
|
||||
export APPRUN_CMD="deepin-wine6-stable"
|
||||
#####wine启动指令,建议
|
||||
EXPORT_ENVS=""
|
||||
|
||||
export SPECIFY_SHELL_DIR=`dirname $START_SHELL_PATH`
|
||||
|
||||
ARCHIVE_FILE_DIR="/opt/apps/$DEB_PACKAGE_NAME/files"
|
||||
|
||||
export WINEDLLPATH=/opt/$APPRUN_CMD/lib:/opt/$APPRUN_CMD/lib64
|
||||
|
||||
export WINEPREDLL="$ARCHIVE_FILE_DIR/dlls"
|
||||
|
||||
DISABLE_ATTACH_FILE_DIALOG=""
|
||||
##默认为空。若为1,则不使用系统自带的文件选择,而是使用wine的
|
||||
##对于deepin/UOS,大部分的应用都不需要使用wine的,如果有需求(比如wine应用选择的限定种类文件系统的文管不支持)
|
||||
##请填1。
|
||||
##注意:因为非DDE的环境不确定,所以默认会在非Deepin/UOS发行版上禁用这个功能。如果你确认在适配的发行版上可以正常启动,请注释或者删除下面这段
|
||||
|
||||
##############<<<<<<<<<禁用文件选择工具开始
|
||||
Get_Dist_Name
|
||||
#此功能实现参见结尾函数段
|
||||
if [ "$DISTRO" != "Deepin" ] && [ "$DISTRO" != "UniontechOS" ];then
|
||||
DISABLE_ATTACH_FILE_DIALOG="1"
|
||||
echo "非deepin/UOS,默认关闭系统自带的文件选择工具,使用Wine的"
|
||||
echo "如果你想改变这个行为,请到/opt/apps/$DEB_PACKAGE_NAME/files/$0处修改"
|
||||
echo "To打包者:如果你要打开自带请注意在适配的发行版上进行测试"
|
||||
echo "To用户:打包者没有打开这个功能,这证明启用这个功能可能造成运行问题。如果你要修改这个行为,请确保你有一定的动手能力"
|
||||
fi
|
||||
##############>>>>>>>>>禁用文件选择工具结束
|
||||
|
||||
##############<<<<<<<<<屏蔽mono和gecko安装器开始
|
||||
##默认屏蔽mono和gecko安装器
|
||||
#if [ "$APPRUN_CMD" = "spark-wine7-devel" ];then
|
||||
|
||||
#export WINEDLLOVERRIDES="mscoree,mshtml="
|
||||
#echo "为了降低打包体积,默认关闭gecko和momo,如有需要,注释此行(仅对spark-wine7-devel有效)"
|
||||
|
||||
#fi
|
||||
##############>>>>>>>>>屏蔽mono和gecko安装器结束
|
||||
|
||||
#########################执行段
|
||||
|
||||
|
||||
|
||||
|
||||
if [ -z "$DISABLE_ATTACH_FILE_DIALOG" ];then
|
||||
export ATTACH_FILE_DIALOG=1
|
||||
fi
|
||||
|
||||
if [ -n "$EXPORT_ENVS" ];then
|
||||
export $EXPORT_ENVS
|
||||
fi
|
||||
|
||||
if [ -n "$EXEC_PATH" ];then
|
||||
if [ -z "${{EXEC_PATH##*.lnk*}}" ];then
|
||||
$START_SHELL_PATH $BOTTLENAME $APPVER "C:/windows/command/start.exe" "/Unix" "$EXEC_PATH" "$@"
|
||||
else
|
||||
$START_SHELL_PATH $BOTTLENAME $APPVER "$EXEC_PATH" "$@"
|
||||
fi
|
||||
else
|
||||
$START_SHELL_PATH $BOTTLENAME $APPVER "uninstaller.exe" "$@"
|
||||
fi'''
|
||||
|
||||
desktopFile = f'''#!/usr/bin/env xdg-open
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
Type=Application
|
||||
X-Created-By=@@@Maintainer@@@
|
||||
Icon=@@@Icon@@@
|
||||
Exec="/opt/apps/@@@Package@@@/files/run.sh"
|
||||
Name=@@@Name@@@
|
||||
Comment=@@@Description@@@
|
||||
MimeType=
|
||||
GenericName=@@@Package@@@
|
||||
Terminal=false
|
||||
StartupNotify=false'''
|
||||
|
||||
def getFileFolderSize(fileOrFolderPath):
|
||||
"""get size for file or folder"""
|
||||
totalSize = 0
|
||||
if not os.path.exists(fileOrFolderPath):
|
||||
return totalSize
|
||||
if os.path.isfile(fileOrFolderPath):
|
||||
totalSize = os.path.getsize(fileOrFolderPath) # 5041481
|
||||
return totalSize
|
||||
if os.path.isdir(fileOrFolderPath):
|
||||
with os.scandir(fileOrFolderPath) as dirEntryList:
|
||||
for curSubEntry in dirEntryList:
|
||||
curSubEntryFullPath = os.path.join(fileOrFolderPath, curSubEntry.name)
|
||||
if curSubEntry.is_dir():
|
||||
curSubFolderSize = getFileFolderSize(curSubEntryFullPath) # 5800007
|
||||
totalSize += curSubFolderSize
|
||||
elif curSubEntry.is_file():
|
||||
curSubFileSize = os.path.getsize(curSubEntryFullPath) # 1891
|
||||
totalSize += curSubFileSize
|
||||
return totalSize
|
||||
|
||||
|
||||
def WriteTxt(path, things):
|
||||
with open(path, "w") as file:
|
||||
file.write(things)
|
||||
|
||||
def ReadTxt(path):
|
||||
things = ""
|
||||
with open(path, "r") as file:
|
||||
things = file.read()
|
||||
return things
|
||||
|
||||
def GetEXEVersion(exePath):
|
||||
versionPath = f"/tmp/wine-runner-exe-version-{random.randint(0, 1000)}.txt"
|
||||
if os.system(f"deepin-wine6-stable '{programPath}/GetEXEVersion.exe' '{exePath}' '{versionPath}'"):
|
||||
return "1.0.0"
|
||||
try:
|
||||
exeVersion = ReadTxt(versionPath).replace("\n", "")
|
||||
if exeVersion.replace(" ", "") == "":
|
||||
return "1.0.0"
|
||||
return exeVersion
|
||||
except:
|
||||
traceback.print_exc()
|
||||
return "1.0.0"
|
||||
|
||||
def StrToByteToStr(text: str):
|
||||
lists = text.split("\\x")
|
||||
for i in range(len(lists)):
|
||||
lists[i]
|
||||
return text
|
||||
|
||||
def UnUseUpperCharPath(path: str):
|
||||
pathList = []
|
||||
lowerList = path.split("/")[1:]
|
||||
for i in lowerList:
|
||||
path = "/" + "/".join(pathList)
|
||||
before = len(pathList)
|
||||
for k in os.listdir(path):
|
||||
if k.lower() == i.lower():
|
||||
pathList.append(k)
|
||||
break
|
||||
end = len(pathList)
|
||||
if before == end:
|
||||
raise OSError("文件路径不存在")
|
||||
return "/" + "/".join(pathList)
|
||||
|
||||
|
||||
class RunThread(QtCore.QThread):
|
||||
showLogText = QtCore.pyqtSignal(str)
|
||||
error = QtCore.pyqtSignal(str)
|
||||
info = QtCore.pyqtSignal(str)
|
||||
question = QtCore.pyqtSignal(str)
|
||||
disbledAll = QtCore.pyqtSignal(bool)
|
||||
cleanPressState = QtCore.pyqtSignal(bool)
|
||||
def RunCommand(self, command):
|
||||
res = subprocess.Popen([command], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
while res.poll() is None:
|
||||
try:
|
||||
text = res.stdout.readline().decode("utf8")
|
||||
except:
|
||||
text = ""
|
||||
self.showLogText.emit(text)
|
||||
print(text, end="")
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
def GetEXEVersion(self, exePath):
|
||||
versionPath = f"/tmp/wine-runner-exe-version-{random.randint(0, 1000)}.txt"
|
||||
self.RunCommand(f"deepin-wine6-stable '{programPath}/GetEXEVersion.exe' '{exePath}' '{versionPath}'")
|
||||
try:
|
||||
exeVersion = ReadTxt(versionPath).replace("\n", "")
|
||||
if exeVersion.replace(" ", "") == "":
|
||||
return "1.0.0"
|
||||
return exeVersion
|
||||
except:
|
||||
traceback.print_exc()
|
||||
return "1.0.0"
|
||||
|
||||
def QuestionMsg(self, text):
|
||||
global questionStatus
|
||||
questionStatus = False
|
||||
self.question.emit(text)
|
||||
while not questionStatus:
|
||||
time.sleep(0.1)
|
||||
print(questionChoose)
|
||||
return questionChoose
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
self.disbledAll.emit(True)
|
||||
if not self.QuestionMsg("在此过程中,需要回答一系列的问题以进行打包,点击确定继续"):
|
||||
self.disbledAll.emit(False)
|
||||
return
|
||||
bottlePath = f"/tmp/deepin-wine-runner-bottle-{random.randint(0, 10000)}"
|
||||
# 清空容器以保证能正常使用
|
||||
if os.path.exists(bottlePath):
|
||||
self.RunCommand(f"rm -rfv '{bottlePath}'")
|
||||
############# 后面将全部调用 deepin wine6 stable 进行操作
|
||||
exeName = os.path.basename(exePath.text())
|
||||
# 暂定
|
||||
debPackageName = "spark-" + xpinyin.Pinyin().get_pinyin(os.path.splitext(exeName)[0].replace(" ", "")).lower().replace("--", "-").replace(" ", "")
|
||||
debPackageVersion = "1.0.0"
|
||||
programIconPath = f"/opt/apps/{debPackageName}/entries/icons/hicolor/scalable/apps/{debPackageName}.png"
|
||||
debMaintainer = os.getlogin()
|
||||
debBuildPath = f"/tmp/deepin-wine-packager-builder-{debPackageName}-{random.randint(0, 1000)}"
|
||||
bottlePackagePath = f"{debBuildPath}/opt/apps/{debPackageName}/files/files.7z"
|
||||
desktopPath = get_desktop_path()
|
||||
self.RunCommand(f"mkdir -pv '{debBuildPath}/DEBIAN'")
|
||||
self.RunCommand(f"mkdir -pv '{debBuildPath}/opt/apps/{debPackageName}/files'")
|
||||
self.RunCommand(f"mkdir -pv '{debBuildPath}/opt/apps/{debPackageName}/entries/applications'")
|
||||
self.RunCommand(f"mkdir -pv '{debBuildPath}/opt/apps/{debPackageName}/entries/icons/hicolor/scalable/apps/'")
|
||||
############## 运行 EXE
|
||||
if self.QuestionMsg("请问此可执行文件是安装包还是绿色软件?是安装包请按 Yes,绿色软件按 No"):
|
||||
# 清空无益处的 lnk 文件
|
||||
lnkPath = f"{bottlePath}/drive_c/ProgramData/Microsoft/Windows/Start Menu/Programs"
|
||||
self.RunCommand(f"rm -rfv '{lnkPath}'")
|
||||
self.RunCommand(f"mkdir -pv '{bottlePath}'")
|
||||
self.RunCommand(f"chmod 777 -Rv '{bottlePath}'")
|
||||
# 禁止生成 .desktop 文件
|
||||
self.RunCommand(f"WINEPREFIX='{bottlePath}' deepin-wine6-stable 'reg' 'add' 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v winemenubuilder.exe '/f'")
|
||||
# 安装包
|
||||
global pressCompleteDownload
|
||||
pressCompleteDownload = False
|
||||
installCmpleteButton.setEnabled(True)
|
||||
self.RunCommand(f"WINEPREFIX='{bottlePath}' deepin-wine6-stable '{exePath.text()}' &") # 非堵塞线程
|
||||
|
||||
# 安装锁,锁解除后才可继续
|
||||
while not pressCompleteDownload:
|
||||
time.sleep(0.1)
|
||||
# 杀死容器内应用
|
||||
self.RunCommand(f"'{programPath}/kill.sh' '{os.path.basename(bottlePath)}'")
|
||||
# 识别 lnk
|
||||
lnkList = GetLnkDesktop(lnkPath)
|
||||
if len(lnkList) <= 0:
|
||||
self.error.emit("无法识别到任何 lnk 快捷方式")
|
||||
self.disbledAll.emit(False)
|
||||
return
|
||||
# 选择最优 lnk
|
||||
secondChooseList = []
|
||||
for k in lnkList:
|
||||
lnkPath = k[0].lower()
|
||||
if "卸载" in lnkPath or "uninstall" in lnkPath or "update" in lnkPath or "网页" in lnkPath or "websize" in lnkPath:
|
||||
continue
|
||||
secondChooseList.append(k)
|
||||
if len(secondChooseList) <= 0:
|
||||
secondChooseList = lnkList
|
||||
rightLnk = secondChooseList[0]
|
||||
miniLenge = len(rightLnk[1])
|
||||
for k in secondChooseList:
|
||||
# 择优选择路径最短一项
|
||||
if len(k[1]) < miniLenge:
|
||||
rightLnk = k
|
||||
miniLenge = len(rightLnk[1])
|
||||
folderExePath = os.path.dirname(rightLnk[1].replace("\\", "/").replace("c:/", bottlePath))
|
||||
exePathInBottle = rightLnk[1]
|
||||
exeName = os.path.splitext(os.path.basename(folderExePath))[0]
|
||||
exePathInSystem = rightLnk[1].replace("\\", "/").replace("c:", f"{bottlePath}/drive_c")
|
||||
debPackageVersion = self.GetEXEVersion(exePathInBottle)
|
||||
cpNow = False
|
||||
for i in iconList:
|
||||
path = i.replace("wineBottonPath", bottlePath).lower()
|
||||
if path == exePathInSystem.lower():
|
||||
self.RunCommand(f"cp -rv '{UnUseUpperCharPath(path)}' '{debBuildPath}/{programIconPath}'")
|
||||
cpNow = True
|
||||
break
|
||||
if not cpNow:
|
||||
self.RunCommand(f"'{programPath}/wrestool' '{UnUseUpperCharPath(exePathInSystem)}' -x -t 14 > '{debBuildPath}/{programIconPath}'")
|
||||
else:
|
||||
#/home/gfdgd_xi/Desktop/新建文件夹1/BeCyIconGrabber.exe
|
||||
# 绿色软件
|
||||
self.RunCommand(f"mkdir -pv '{bottlePath}'")
|
||||
self.RunCommand(f"chmod 777 -Rv '{bottlePath}'")
|
||||
self.RunCommand(f"WINEPREFIX='{bottlePath}' deepin-wine6-stable exit")
|
||||
folderExePath = os.path.dirname(exePath.text())
|
||||
exePathInBottle = f"c:/Program Files/{os.path.basename(folderExePath)}/{exeName}"
|
||||
exeName = os.path.splitext(os.path.basename(os.path.basename(exePath.text())))[0]
|
||||
self.RunCommand(f"'{programPath}/wrestool' '{exePathInBottle}' -x -t 14 > '{debBuildPath}/{programIconPath}'")
|
||||
debPackageVersion = self.GetEXEVersion(exePathInBottle)
|
||||
# 拷贝文件到容器
|
||||
self.RunCommand(f"cp -rv '{folderExePath}' '{bottlePath}/drive_c/Program Files'")
|
||||
debDescription = f"{exeName} By Deepin Wine 6 Stable And Build By Wine Runner"
|
||||
debDepends = "deepin-wine6-stable, spark-dwine-helper | store.spark-app.spark-dwine-helper, fonts-wqy-microhei, fonts-wqy-zenhei"
|
||||
############ 处理容器
|
||||
# 对用户目录进行处理
|
||||
os.chdir(bottlePath)
|
||||
self.RunCommand("sed -i \"s#$USER#@current_user@#\" ./*.reg")
|
||||
os.chdir(f"{bottlePath}/drive_c/users")
|
||||
# 如果缩放文件 scale.txt 存在,需要移除以便用户自行调节缩放设置
|
||||
if os.path.exists(f"{bottlePath}/scale.txt"):
|
||||
self.RunCommand(f"rm -rfv '{bottlePath}/scale.txt'")
|
||||
# 删除因为脚本失误导致用户目录嵌套(如果存在)
|
||||
if os.path.exists(f"{bottlePath}/drive_c/users/@current_user@/@current_user@"):
|
||||
self.RunCommand(f"rm -rfv '{bottlePath}/drive_c/users/@current_user@/@current_user@'")
|
||||
self.RunCommand(f"mv -fv '{os.getlogin()}' @current_user@")
|
||||
self.RunCommand(f"rm -fv '{bottlePath}/drive_c/users/@current_user@/我的'*")
|
||||
self.RunCommand(f"rm -fv '{bottlePath}/drive_c/users/@current_user@/My '*")
|
||||
self.RunCommand(f"rm -fv '{bottlePath}/drive_c/users/@current_user@/Desktop'")
|
||||
self.RunCommand(f"rm -fv '{bottlePath}/drive_c/users/@current_user@/Downloads'")
|
||||
self.RunCommand(f"rm -fv '{bottlePath}/drive_c/users/@current_user@/Templates'")
|
||||
########### 打包容器
|
||||
self.RunCommand(f"7z a '{bottlePackagePath}' '{bottlePath}/'*")
|
||||
########### 生成文件内容
|
||||
buildProgramSize = getFileFolderSize(debBuildPath)
|
||||
replaceMap = [
|
||||
["@@@Package@@@", debPackageName],
|
||||
["@@@Version@@@", debPackageVersion],
|
||||
["@@@Maintainer@@@", debMaintainer],
|
||||
["@@@Depends@@@", debDepends],
|
||||
["@@@Description@@@", debDescription],
|
||||
["@@@Installed-Size@@@", str(buildProgramSize)],
|
||||
["@@@Name@@@", exeName],
|
||||
["@@@EXEC_PATH@@@", exePathInBottle],
|
||||
["@@@Icon@@@", programIconPath]
|
||||
]
|
||||
debControl = ReplaceText(control, replaceMap)
|
||||
debPostrm = ReplaceText(postrm, replaceMap)
|
||||
debInfo = ReplaceText(info, replaceMap)
|
||||
debRunSh = ReplaceText(runsh, replaceMap)
|
||||
debDesktop = ReplaceText(desktopFile, replaceMap)
|
||||
########### 写入文件
|
||||
WriteTxt(f"{debBuildPath}/opt/apps/{debPackageName}/entries/applications/{debPackageName}.desktop", debDesktop)
|
||||
WriteTxt(f"{debBuildPath}/opt/apps/{debPackageName}/files/run.sh", debRunSh)
|
||||
WriteTxt(f"{debBuildPath}/opt/apps/{debPackageName}/info", debInfo)
|
||||
WriteTxt(f"{debBuildPath}/DEBIAN/control", debControl)
|
||||
WriteTxt(f"{debBuildPath}/DEBIAN/postrm", debPostrm)
|
||||
########### 赋值权限
|
||||
self.RunCommand(f"chmod -Rv 644 '{debBuildPath}/opt/apps/{debPackageName}/info'")
|
||||
self.RunCommand(f"chmod -Rv 0755 '{debBuildPath}/DEBIAN'")
|
||||
self.RunCommand(f"chmod -Rv 755 '{debBuildPath}/opt/apps/{debPackageName}/files/'*.sh")
|
||||
self.RunCommand(f"chmod -Rv 755 '{debBuildPath}/opt/apps/{debPackageName}/entries/applications/'*.desktop")
|
||||
########### 打包 deb
|
||||
print(debPackageVersion)
|
||||
self.RunCommand(f"dpkg -b '{debBuildPath}' '{desktopPath}/{debPackageName}_{debPackageVersion}_i386.deb'")
|
||||
self.info.emit("打包完成!")
|
||||
self.disbledAll.emit(False)
|
||||
########### 移除临时文件
|
||||
#self.RunCommand(f"rm -rfv '{debBuildPath}' > /dev/null")
|
||||
#self.RunCommand(f"rm -rfv '{bottlePath}' > /dev/null")
|
||||
except:
|
||||
#self.RunCommand(f"rm -rfv '{debBuildPath}' > /dev/null")
|
||||
#self.RunCommand(f"rm -rfv '{bottlePath}' > /dev/null")
|
||||
# 若打包出现任何错误
|
||||
traceback.print_exc()
|
||||
self.error.emit(f"打包错误,详细详细如下:{traceback.format_exc()}")
|
||||
self.showLogText.emit(traceback.format_exc())
|
||||
self.disbledAll.emit(False)
|
||||
|
||||
#/home/gfdgd_xi/Downloads/XPcalc.exe
|
||||
def RunBuildThread():
|
||||
global buildThread
|
||||
buildThread = RunThread()
|
||||
buildThread.showLogText.connect(ShowText)
|
||||
buildThread.error.connect(ErrorMessage)
|
||||
buildThread.info.connect(InformationMessage)
|
||||
buildThread.question.connect(QuestionMessage)
|
||||
buildThread.disbledAll.connect(DisbledAndEnabledAll)
|
||||
buildThread.cleanPressState.connect(CleanPressCompleteDownloadState)
|
||||
buildThread.start()
|
||||
|
||||
pressCompleteDownload = False
|
||||
|
||||
def PressCompleteDownload():
|
||||
global pressCompleteDownload
|
||||
pressCompleteDownload = True
|
||||
installCmpleteButton.setDisabled(True)
|
||||
|
||||
def BrowserExe():
|
||||
filePath = QtWidgets.QFileDialog.getOpenFileName(window, "选择 exe", get_home(), "可执行文件(*.exe);;所有文件(*.*)")
|
||||
if filePath[0] != "" or filePath[0] != None:
|
||||
exePath.setText(filePath[0])
|
||||
|
||||
if __name__ == "__main__":
|
||||
programPath = os.path.split(os.path.realpath(__file__))[0] # 返回 string
|
||||
iconPath = "{}/deepin-wine-runner.svg".format(programPath)
|
||||
information = json.loads(ReadTxt(f"{programPath}/information.json"))
|
||||
iconListUnBuild = json.loads(ReadTxt(f"{programPath}/IconList.json"))[0]
|
||||
iconList = json.loads(ReadTxt(f"{programPath}/IconList.json"))[1]
|
||||
for i in iconListUnBuild:
|
||||
iconList.append(i)
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
version = information["Version"]
|
||||
window = QtWidgets.QMainWindow()
|
||||
widget = QtWidgets.QWidget()
|
||||
layout = QtWidgets.QGridLayout()
|
||||
exePath = QtWidgets.QLineEdit()
|
||||
browserExeButton = QtWidgets.QPushButton("浏览……")
|
||||
logText = QtWidgets.QTextBrowser()
|
||||
logText.setStyleSheet("""
|
||||
background-color: black;
|
||||
color: white;
|
||||
""")
|
||||
controlLayout = QtWidgets.QHBoxLayout()
|
||||
buildButton = QtWidgets.QPushButton("现在打包……")
|
||||
installCmpleteButton = QtWidgets.QPushButton("安装程序执行完成")
|
||||
browserExeButton.clicked.connect(BrowserExe)
|
||||
buildButton.clicked.connect(RunBuildThread)
|
||||
installCmpleteButton.clicked.connect(PressCompleteDownload)
|
||||
installCmpleteButton.setDisabled(True)
|
||||
controlLayout.addWidget(buildButton)
|
||||
controlLayout.addWidget(installCmpleteButton)
|
||||
layout.addWidget(QtWidgets.QLabel("选择 EXE:"), 0, 0)
|
||||
layout.addWidget(exePath, 0, 1)
|
||||
layout.addWidget(browserExeButton, 0, 2)
|
||||
layout.addLayout(controlLayout, 1, 1)
|
||||
layout.addWidget(logText, 2, 0, 1, 3)
|
||||
widget.setLayout(layout)
|
||||
window.setCentralWidget(widget)
|
||||
window.setWindowTitle(f"Wine 运行器 {version}——简易打包器")
|
||||
window.show()
|
||||
sys.exit(app.exec_())
|
||||
# ./wrestool ../Desktop/deep-wine-runner/geek.exe -x -t 14 > a.png
|
||||
# Flag:
|
||||
# 1、不想打包了,强制终止功能
|
||||
# 2、版本号自动识别
|
||||
# 3、包名自动识别
|
||||
@@ -203,9 +203,36 @@ def Build7zButton_Clicked():
|
||||
QT.thread.start()
|
||||
|
||||
def make_deb(build=False):
|
||||
global bottleNameLock
|
||||
clean_textbox1_things()
|
||||
disabled_or_NORMAL_all(False)
|
||||
if e1_text.text() == "" or e2_text.text() == "" or e3_text.text() == "" or e4_text.text() == "" or e5_text.text() == "" or e6_text.text() == "" or e7_text.text() == "" or e8_text.text() == "" or e12_text.text() == "":
|
||||
badComplete = False
|
||||
# 规范检测
|
||||
if e1_text.text().lower() != e1_text.text():
|
||||
if QtWidgets.QMessageBox.warning(window, "提示", f"包名 {e1_text.text()} 似乎不符合规范,可能会导致打包后的包无法投稿到应用商店,是否继续?\n可参考 deb 安装包打包标准", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) == QtWidgets.QMessageBox.No:
|
||||
disabled_or_NORMAL_all(True)
|
||||
label13_text_change("用户已取消")
|
||||
return
|
||||
for i in range(len(iconUiList)):
|
||||
if os.path.splitext(iconUiList[i][4].text())[1] == ".ico":
|
||||
if QtWidgets.QMessageBox.warning(window, "提示", f"图标 {iconUiList[i][4].text()} 似乎为 ico 格式,可能会导致打包后的程序在启动器的图标无法正常显示,是否继续?", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) == QtWidgets.QMessageBox.No:
|
||||
disabled_or_NORMAL_all(True)
|
||||
label13_text_change("用户已取消")
|
||||
return
|
||||
if os.path.exists(iconUiList[i][0].text()) and not "c:" in iconUiList[i][0].text().lower():
|
||||
if not e6_text.text() in iconUiList[i][0].text():
|
||||
if QtWidgets.QMessageBox.warning(window, "提示", f"路径 {iconUiList[i][0].text()} 似乎不符合规范且不位于容器内,可能会导致打包后的程序无法运行,是否继续?\n可参考 Windows 下的文件路径", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) == QtWidgets.QMessageBox.No:
|
||||
disabled_or_NORMAL_all(True)
|
||||
label13_text_change("用户已取消")
|
||||
return
|
||||
if QtWidgets.QMessageBox.warning(window, "提示", f"路径 {iconUiList[i][0].text()} 似乎不符合规范,可能会导致打包后的程序无法运行,是否继续?\n可参考 Windows 下的文件路径", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) == QtWidgets.QMessageBox.No:
|
||||
disabled_or_NORMAL_all(True)
|
||||
label13_text_change("用户已取消")
|
||||
return
|
||||
for k in [0, 3]:
|
||||
if iconUiList[i][k].text().replace(" ", "") == "":
|
||||
badComplete = True
|
||||
if badComplete or e1_text.text() == "" or e2_text.text() == "" or e3_text.text() == "" or e4_text.text() == "" or e5_text.text() == "" or e6_text.text() == "" or e7_text.text() == "" or e8_text.text() == "" or e12_text.text() == "":
|
||||
QtWidgets.QMessageBox.critical(widget, "错误", "必填信息没有填写完整,无法继续构建 deb 包")
|
||||
disabled_or_NORMAL_all(True)
|
||||
label13_text_change("必填信息没有填写完整,无法继续构建 deb 包")
|
||||
@@ -232,6 +259,7 @@ def make_deb(build=False):
|
||||
QT.thread.errorMsg.connect(ErrorMsg)
|
||||
QT.thread.infoMsg.connect(InfoMsg)
|
||||
QT.thread.disabled_or_NORMAL_all.connect(disabled_or_NORMAL_all)
|
||||
bottleNameLock = False
|
||||
QT.thread.start()
|
||||
#thread.start()
|
||||
|
||||
@@ -245,7 +273,6 @@ def ReplaceText(string: str, lists: list):
|
||||
return string
|
||||
|
||||
class make_deb_threading(QtCore.QThread):
|
||||
|
||||
signal = QtCore.pyqtSignal(str)
|
||||
label = QtCore.pyqtSignal(str)
|
||||
getSavePath = QtCore.pyqtSignal(str)
|
||||
@@ -1324,6 +1351,12 @@ StartupNotify=false
|
||||
self.label.emit("正在构建 deb 包……")
|
||||
self.run_command("bash -c 'dpkg -b \"{}\" \"{}\"'".format(debPackagePath, e12_text.text()))
|
||||
################
|
||||
# 删除临时文件
|
||||
################
|
||||
if not self.build:
|
||||
self.label.emit("正在删除临时文件……")
|
||||
self.run_command(f"rm -rfv '{debPackagePath}'")
|
||||
################
|
||||
# 完成构建
|
||||
################
|
||||
self.label.emit("完成构建!")
|
||||
@@ -1705,9 +1738,9 @@ def AddTab():
|
||||
desktopIconTabLayout = QtWidgets.QGridLayout()
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "wine 容器里需要运行的可执行文件路径(※必填):")), 6, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要显示的 .desktop 文件的分类(※必填):")), 7, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "wine 容器里需要运行的可执行文件的参数(选填):")), 8, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "wine 容器里需要运行的可执行文件的参数:")), 8, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要显示的 .desktop 文件的名称(※必填):")), 9, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要显示的 .desktop 文件的图标(选填):")), 10, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要显示的 .desktop 文件的图标:")), 10, 0, 1, 1)
|
||||
iconTab1.setLayout(desktopIconTabLayout)
|
||||
desktopIconTab.addTab(iconTab1, f"图标{desktopIconTab.count() + 1}")
|
||||
desktopIconTabLayout.addWidget(e7_text, 6, 1, 1, 1)
|
||||
@@ -1717,6 +1750,8 @@ def AddTab():
|
||||
desktopIconTabLayout.addWidget(e9_text, 10, 1, 1, 1)
|
||||
desktopIconTabLayout.addWidget(button2, 10, 2, 1, 1)
|
||||
e7_text.textChanged.connect(ChangeTapTitle)
|
||||
e7_text.setPlaceholderText("例如 c:/Program Files/Tencent/QQ/Bin/QQ.exe")
|
||||
e9_text.setPlaceholderText("支持 png 和 svg 格式,不支持 ico 格式")
|
||||
iconUiList.append([e7_text, option1_text, e15_text, e8_text, e9_text])
|
||||
print(iconUiList)
|
||||
|
||||
@@ -1727,6 +1762,26 @@ def DelTab():
|
||||
del iconUiList[desktopIconTab.currentIndex()]
|
||||
desktopIconTab.removeTab(desktopIconTab.currentIndex())
|
||||
|
||||
def ChangeBottleName():
|
||||
global bottleNameLock
|
||||
global bottleNameChangeLock
|
||||
e1_text.setText(e1_text.text().replace(" ", ""))
|
||||
if bottleNameLock:
|
||||
return
|
||||
if os.path.basename(e6_text.text()) == ".wine" or e6_text.text() == "":
|
||||
bottleNameChangeLock = True
|
||||
e5_text.setText(e1_text.text())
|
||||
return
|
||||
bottleNameChangeLock = True
|
||||
e5_text.setText(os.path.basename(e6_text.text().replace(" ", "")))
|
||||
|
||||
def LockBottleName():
|
||||
global bottleNameLock
|
||||
if bottleNameChangeLock:
|
||||
return
|
||||
bottleNameLock = True
|
||||
|
||||
bottleNameLock = False
|
||||
###############
|
||||
# 程序信息
|
||||
###############
|
||||
@@ -1820,14 +1875,17 @@ buildDebDir.clicked.connect(lambda: make_deb(True))
|
||||
build7z.clicked.connect(Build7zButton_Clicked)
|
||||
installDeb.clicked.connect(InstallDeb)
|
||||
wineFrame.addWidget(wineVersion)
|
||||
e1_text.textChanged.connect(ChangeBottleName)
|
||||
e5_text.textChanged.connect(LockBottleName)
|
||||
e6_text.textChanged.connect(ChangeBottleName)
|
||||
e7_text.textChanged.connect(ChangeTapTitle)
|
||||
# 创建控件
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要打包的 deb 包的包名(※必填):")), 0, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要打包的 deb 包的版本号(※必填):")), 1, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要打包的 deb 包的说明(※必填):")), 2, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要打包的 deb 包的维护者(※必填):")), 3, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "deb 包的版本号(※必填):")), 1, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "deb 包的说明(※必填):")), 2, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "deb 包的维护者(※必填):")), 3, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要解压的 wine 容器的容器名(※必填):")), 4, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要解压的 wine 容器(※必填):")), 5, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要打包的 wine 容器(※必填):")), 5, 0, 1, 1)
|
||||
desktopIconTab = QtWidgets.QTabWidget()
|
||||
controlWidget = QtWidgets.QWidget()
|
||||
controlWidgetLayout = QtWidgets.QHBoxLayout()
|
||||
@@ -1842,9 +1900,9 @@ iconTab1 = QtWidgets.QWidget()
|
||||
desktopIconTabLayout = QtWidgets.QGridLayout()
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "wine 容器里需要运行的可执行文件路径(※必填):")), 6, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要显示的 .desktop 文件的分类(※必填):")), 7, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "wine 容器里需要运行的可执行文件的参数(选填):")), 8, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "wine 容器里需要运行的可执行文件的参数:")), 8, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要显示的 .desktop 文件的名称(※必填):")), 9, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要显示的 .desktop 文件的图标(选填):")), 10, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要显示的 .desktop 文件的图标:")), 10, 0, 1, 1)
|
||||
iconTab1.setLayout(desktopIconTabLayout)
|
||||
#desktopIconTab.setTabPosition(QtWidgets.QTabWidget.East)
|
||||
desktopIconTab.addTab(iconTab1, "Defult")
|
||||
@@ -1911,6 +1969,10 @@ e2_text.textChanged.connect(AutoPathSet)
|
||||
debArch.currentIndexChanged.connect(AutoPathSet)
|
||||
debArch.currentIndexChanged.connect(ChangeArchCombobox)
|
||||
e12_text.textChanged.connect(UserPathSet)
|
||||
e1_text.setPlaceholderText("例如 spark-deepin-wine-runner,不建议有大写字符")
|
||||
e2_text.setPlaceholderText(f"例如 {version}")
|
||||
e7_text.setPlaceholderText("例如 c:/Program Files/Tencent/QQ/Bin/QQ.exe")
|
||||
e9_text.setPlaceholderText("支持 png 和 svg 格式,不支持 ico 格式")
|
||||
# 菜单栏
|
||||
menu = window.menuBar()
|
||||
programmenu = menu.addMenu(QtCore.QCoreApplication.translate("U", "程序"))
|
||||
@@ -1927,6 +1989,7 @@ else:
|
||||
uploadSparkStoreProgram = QtWidgets.QAction(QtCore.QCoreApplication.translate("U", "使用投稿器投稿(推荐,请先安装投稿器)"))
|
||||
uploadSparkStoreProgram.setDisabled(True)
|
||||
tip = QtWidgets.QAction(QtCore.QCoreApplication.translate("U", "小提示"))
|
||||
getPdfHelp = QtWidgets.QAction(QtCore.QCoreApplication.translate("U", "Wine 运行器和 Wine 打包器傻瓜式使用教程(小白专用)\nBy @雁舞白沙"))
|
||||
exit.triggered.connect(window.close)
|
||||
tip.triggered.connect(helps)
|
||||
programmenu.addAction(exit)
|
||||
@@ -1938,7 +2001,9 @@ debE.triggered.connect(lambda: ReadDeb(False))
|
||||
debX.triggered.connect(lambda: ReadDeb(True))
|
||||
uploadSparkStoreWebsize.triggered.connect(lambda: webbrowser.open_new_tab("https://upload.deepinos.org"))
|
||||
uploadSparkStoreProgram.triggered.connect(lambda: threading.Thread(target=os.system, args=[f"/opt/spark-store-submitter/bin/spark-store-submitter '{e12_text.text()}'"]).start())
|
||||
getPdfHelp.triggered.connect(lambda: webbrowser.open_new_tab("https://gitee.com/gfdgd-xi/deep-wine-runner/raw/main/Wine%E8%BF%90%E8%A1%8C%E5%99%A8%E5%92%8CWine%E6%89%93%E5%8C%85%E5%99%A8%E5%82%BB%E7%93%9C%E5%BC%8F%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B%EF%BC%88%E5%B0%8F%E7%99%BD%E4%B8%93%E7%94%A8%EF%BC%8920221126-V2.pdf"))
|
||||
help.addAction(tip)
|
||||
help.addAction(getPdfHelp)
|
||||
# 控件配置
|
||||
try:
|
||||
e6_text.setText(sys.argv[1].replace("~", get_home()))
|
||||
|
||||
69
demo/GetExeVersion/main.cpp
Normal file
69
demo/GetExeVersion/main.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
/**********************************
|
||||
* <20><><EFBFBD>ߣ<EFBFBD>gfdgd xi<78><69>Ϊʲô<CAB2><C3B4><EFBFBD><EFBFBD>ϲ<EFBFBD><CFB2><EFBFBD>ܳ<EFBFBD>û<EFBFBD>Ͱ<EFBFBD><CDB0><EFBFBD><EFBFBD><EFBFBD>
|
||||
* <20>汾<EFBFBD><E6B1BE>2.5.0
|
||||
* <20><><EFBFBD><EFBFBD>ʱ<EFBFBD>䣺2022<32><32>11<31><31>27<32><37>
|
||||
* ֻ<><D6BB><EFBFBD><EFBFBD> Wine/Windows <20><><EFBFBD><EFBFBD>
|
||||
**********************************/
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <Windows.h>
|
||||
#pragma comment(lib, "version.lib");
|
||||
using namespace std;
|
||||
|
||||
// <20>ȿӡ<C8BF><D3A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA> Dev CPP <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>ڱ<EFBFBD><DAB1><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD> -lversion
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC>汾<EFBFBD><E6B1BE>
|
||||
//@params:filename:<3A>ļ<EFBFBD><C4BC><EFBFBD>
|
||||
string GetFileVersion(LPCWSTR filename)
|
||||
{
|
||||
string asVer = "";
|
||||
VS_FIXEDFILEINFO *pVsInfo;
|
||||
unsigned int iFileInfoSize = sizeof(VS_FIXEDFILEINFO);
|
||||
int iVerInfoSize = GetFileVersionInfoSizeW(filename, NULL);
|
||||
if(iVerInfoSize != 0)
|
||||
{
|
||||
char *pBuf = NULL;
|
||||
|
||||
while(!pBuf)
|
||||
{
|
||||
pBuf = new char[iVerInfoSize];
|
||||
}
|
||||
if(GetFileVersionInfoW(filename, 0, iVerInfoSize, pBuf))
|
||||
{
|
||||
if(VerQueryValueA(pBuf, "\\", (void **)&pVsInfo, &iFileInfoSize))
|
||||
{
|
||||
sprintf(pBuf, "%d.%d.%d.%d", HIWORD(pVsInfo->dwFileVersionMS), LOWORD(pVsInfo->dwFileVersionMS), HIWORD(pVsInfo->dwFileVersionLS), LOWORD(pVsInfo->dwFileVersionLS));
|
||||
asVer = pBuf;
|
||||
}
|
||||
}
|
||||
delete pBuf;
|
||||
}
|
||||
return asVer;
|
||||
}
|
||||
|
||||
// <20><>ʽת<CABD><D7AA>
|
||||
LPWSTR ConvertCharToLPWSTR(const char* szString)
|
||||
{
|
||||
int dwLen = strlen(szString) + 1;
|
||||
int nwLen = MultiByteToWideChar(CP_ACP, 0, szString, dwLen, NULL, 0);//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵij<CAB5><C4B3><EFBFBD>
|
||||
LPWSTR lpszPath = new WCHAR[dwLen];
|
||||
MultiByteToWideChar(CP_ACP, 0, szString, dwLen, lpszPath, nwLen);
|
||||
return lpszPath;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]){
|
||||
if (argc < 2){
|
||||
cout << "Unfull Option" << endl;
|
||||
return 1;
|
||||
}
|
||||
string version = GetFileVersion(ConvertCharToLPWSTR(argv[1]));
|
||||
cout << "Version: " << version << endl;
|
||||
if (argc == 3){
|
||||
cout << "Write To " << argv[2] << endl;
|
||||
// Ϊ<>˷<EFBFBD><CBB7><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1>д<EFBFBD><D0B4><EFBFBD>ı<EFBFBD><C4B1>ĵ<EFBFBD>
|
||||
ofstream write(argv[2], ios::trunc);
|
||||
write << version;
|
||||
write.close();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
BIN
demo/GetExeVersion/main.exe
Executable file
BIN
demo/GetExeVersion/main.exe
Executable file
Binary file not shown.
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"Version": "2.5.0",
|
||||
"Thank": [
|
||||
"感谢 @雁舞白沙 专门为小白用户编写的使用 Wine 运行器非基于生态适配脚本的程序打包教程",
|
||||
"感谢 @牦牛儿苗 进行了龙芯 3a5000 平台的测试与移植",
|
||||
"感谢 @雁舞白沙 优化了程序文案",
|
||||
"感谢 @豪 的程序测试和制作的非官方论坛 https://gfdgdxi.flarum.cloud/",
|
||||
|
||||
@@ -1808,6 +1808,7 @@ def UploadLog():
|
||||
traceback.print_exc()
|
||||
QtWidgets.QMessageBox.critical(window, "错误", "上传失败!")
|
||||
|
||||
|
||||
def SaveLog():
|
||||
path = QtWidgets.QFileDialog.getSaveFileName(window, "保存日志", get_home(), "txt文件(*.txt);;html 文件(*.html);;所有文件(*.*))")
|
||||
if not path[1]:
|
||||
@@ -1975,22 +1976,25 @@ except:
|
||||
def getFileFolderSize(fileOrFolderPath):
|
||||
"""get size for file or folder"""
|
||||
totalSize = 0
|
||||
if not os.path.exists(fileOrFolderPath):
|
||||
return totalSize
|
||||
if os.path.isfile(fileOrFolderPath):
|
||||
totalSize = os.path.getsize(fileOrFolderPath) # 5041481
|
||||
return totalSize
|
||||
if os.path.isdir(fileOrFolderPath):
|
||||
with os.scandir(fileOrFolderPath) as dirEntryList:
|
||||
for curSubEntry in dirEntryList:
|
||||
curSubEntryFullPath = os.path.join(fileOrFolderPath, curSubEntry.name)
|
||||
if curSubEntry.is_dir():
|
||||
curSubFolderSize = getFileFolderSize(curSubEntryFullPath) # 5800007
|
||||
totalSize += curSubFolderSize
|
||||
elif curSubEntry.is_file():
|
||||
curSubFileSize = os.path.getsize(curSubEntryFullPath) # 1891
|
||||
totalSize += curSubFileSize
|
||||
try:
|
||||
if not os.path.exists(fileOrFolderPath):
|
||||
return totalSize
|
||||
if os.path.isfile(fileOrFolderPath):
|
||||
totalSize = os.path.getsize(fileOrFolderPath) # 5041481
|
||||
return totalSize
|
||||
if os.path.isdir(fileOrFolderPath):
|
||||
with os.scandir(fileOrFolderPath) as dirEntryList:
|
||||
for curSubEntry in dirEntryList:
|
||||
curSubEntryFullPath = os.path.join(fileOrFolderPath, curSubEntry.name)
|
||||
if curSubEntry.is_dir():
|
||||
curSubFolderSize = getFileFolderSize(curSubEntryFullPath) # 5800007
|
||||
totalSize += curSubFolderSize
|
||||
elif curSubEntry.is_file():
|
||||
curSubFileSize = os.path.getsize(curSubEntryFullPath) # 1891
|
||||
totalSize += curSubFileSize
|
||||
return totalSize
|
||||
except:
|
||||
return totalSize
|
||||
|
||||
# 获取当前语言
|
||||
def get_now_lang()->"获取当前语言":
|
||||
@@ -2186,33 +2190,8 @@ try:
|
||||
threading.Thread(target=requests.get, args=[parse.unquote(base64.b64decode("aHR0cDovLzEyMC4yNS4xNTMuMTQ0L3NwYXJrLWRlZXBpbi13aW5lLXJ1bm5lci9vcGVuL0luc3RhbGwucGhw").decode("utf-8")) + "?Version=" + version]).start()
|
||||
except:
|
||||
pass
|
||||
iconListUnBuild = [
|
||||
["QQ", "wineBottonPath/drive_c/Program Files/Tencent/QQ/Bin/QQ.exe"],
|
||||
["QQ", "wineBottonPath/drive_c/Program Files (x86)/Tencent/QQ/Bin/QQ.exe"],
|
||||
["TIM", "wineBottonPath/drive_c/Program Files/Tencent/TIM/Bin/TIM.exe"],
|
||||
["TIM", "wineBottonPath/drive_c/Program Files (x86)/Tencent/TIM/Bin/TIM.exe"]
|
||||
]
|
||||
iconList = [
|
||||
["cmd", "cmd"],
|
||||
["cmd", "cmd.exe"],
|
||||
["cmd", "wineBottonPath/drive_c/windows/system32/cmd.exe"],
|
||||
["Internet Explorer", "iexplore"],
|
||||
["Internet Explorer", "iexplore.exe"],
|
||||
["Internet Explorer", "wineBottonPath/drive_c/Program Files/Internet Explorer/iexplore.exe"],
|
||||
["Internet Explorer", "wineBottonPath/drive_c/Program Files (x86)/Internet Explorer/iexplore.exe"],
|
||||
["微信", "wineBottonPath/drive_c/Program Files/Tencent/WeChat/WeChat.exe"],
|
||||
["微信", "wineBottonPath/drive_c/Program Files (x86)/Tencent/WeChat/WeChat.exe"],
|
||||
["UltraISO", "wineBottonPath/drive_c/Program Files/UltraISO/UltraISO.exe"],
|
||||
["UltraISO", "wineBottonPath/drive_c/Program Files (x86)/UltraISO/UltraISO.exe"],
|
||||
["迅雷", "wineBottonPath/drive_c/Program Files/Thunder Network/MiniThunder/Bin/ThunderMini.exe"],
|
||||
["迅雷", "wineBottonPath/drive_c/Program Files (x86)/Thunder Network/MiniThunder/Bin/ThunderMini.exe"],
|
||||
["Microsoft Office Word", "wineBottonPath/drive_c/Program Files/Microsoft Office/Office12/WINWORD.EXE"],
|
||||
["Microsoft Office Word", "wineBottonPath/drive_c/Program Files (x86)/Microsoft Office/Office12/WINWORD.EXE"],
|
||||
["腾讯会议", "wineBottonPath/drive_c/Program Files/Tencent/WeMeet/wemeetapp.exe"],
|
||||
["腾讯会议", "wineBottonPath/drive_c/Program Files (x86)/Tencent/WeMeet/wemeetapp.exe"],
|
||||
["腾讯课堂", "wineBottonPath/drive_c/Program Files/Tencent/EDU/bin/TXEDU.exe"],
|
||||
["腾讯课堂", "wineBottonPath/drive_c/Program Files (x86)/Tencent/EDU/bin/TXEDU.exe"]
|
||||
]
|
||||
iconListUnBuild = json.loads(readtxt(f"{programPath}/IconList.json"))[0]
|
||||
iconList = json.loads(readtxt(f"{programPath}/IconList.json"))[1]
|
||||
for i in iconListUnBuild:
|
||||
iconList.append(i)
|
||||
print(iconList)
|
||||
|
||||
Reference in New Issue
Block a user