mirror of
https://github.com/HIllya51/LunaTranslator.git
synced 2025-01-15 00:43:59 +08:00
test
Update retrieval.py
This commit is contained in:
parent
a7bc3574d3
commit
5234c555e7
10
.github/workflows/build.yml
vendored
10
.github/workflows/build.yml
vendored
@ -14,16 +14,8 @@ jobs:
|
|||||||
include:
|
include:
|
||||||
- architecture: x86
|
- architecture: x86
|
||||||
fname: LunaTranslator_x86
|
fname: LunaTranslator_x86
|
||||||
debug: 0
|
|
||||||
- architecture: x64
|
- architecture: x64
|
||||||
fname: LunaTranslator
|
fname: LunaTranslator
|
||||||
debug: 0
|
|
||||||
- architecture: x86
|
|
||||||
fname: LunaTranslator_x86_debug
|
|
||||||
debug: 1
|
|
||||||
- architecture: x64
|
|
||||||
fname: LunaTranslator_debug
|
|
||||||
debug: 1
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@ -45,7 +37,7 @@ jobs:
|
|||||||
run: pip install cmake pefile requests
|
run: pip install cmake pefile requests
|
||||||
- name: Run build script
|
- name: Run build script
|
||||||
run: |
|
run: |
|
||||||
python build.py ${{ matrix.architecture }} ${{ matrix.debug }}
|
python build.py ${{ matrix.architecture }}
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.fname }}
|
name: ${{ matrix.fname }}
|
||||||
|
@ -3,3 +3,4 @@ import pytz
|
|||||||
import uuid
|
import uuid
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import configparser
|
@ -1 +1,2 @@
|
|||||||
python pack.py 1
|
@REM python pack.py 1
|
||||||
|
%LOCALAPPDATA%\Programs\Python\Python37-32\python.exe retrieval.py 1
|
@ -1 +1,2 @@
|
|||||||
python pack.py 0
|
@REM python pack.py 0
|
||||||
|
%LOCALAPPDATA%\Programs\Python\Python37\python.exe retrieval.py 0
|
@ -1,6 +1,4 @@
|
|||||||
PyQt5==5.15.10
|
PyQt5==5.15.10
|
||||||
PyQt5-Qt5==5.15.2
|
PyQt5-Qt5==5.15.2
|
||||||
webviewpy
|
webviewpy==1.2.0
|
||||||
nuitka==2.2
|
|
||||||
imageio
|
|
||||||
pefile
|
pefile
|
275
LunaTranslator/retrieval.py
Normal file
275
LunaTranslator/retrieval.py
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
import modulefinder, shutil, os, sys, pefile
|
||||||
|
import builtins
|
||||||
|
|
||||||
|
x86 = int(sys.argv[1]) if len(sys.argv) > 1 else 0
|
||||||
|
if x86:
|
||||||
|
downlevel = r"C:\Windows\SysWOW64\downlevel"
|
||||||
|
src = py37Pathlocal = (
|
||||||
|
os.environ["LOCALAPPDATA"] + r"\Programs\Python\Python37-32" + "\\"
|
||||||
|
)
|
||||||
|
tgt = r"..\build\LunaTranslator_x86\LunaTranslator\runtime"
|
||||||
|
targetdir = r"..\build\LunaTranslator_x86"
|
||||||
|
launch = r"..\plugins\builds\_x86"
|
||||||
|
baddll = "DLL64"
|
||||||
|
gooddll = "DLL32"
|
||||||
|
py37Path = "C:\\hostedtoolcache\\windows\\Python\\3.7.9\\x86\\python.exe"
|
||||||
|
py37Pathlocal = (
|
||||||
|
os.environ["LOCALAPPDATA"] + r"\Programs\Python\Python37-32\python.exe"
|
||||||
|
)
|
||||||
|
webviewappendix = r"Lib\site-packages\webviewpy\platform\win32\x86\webview.dll"
|
||||||
|
else:
|
||||||
|
baddll = "DLL32"
|
||||||
|
gooddll = "DLL64"
|
||||||
|
launch = r"..\plugins\builds\_x64"
|
||||||
|
tgt = r"..\build\LunaTranslator\LunaTranslator\runtime"
|
||||||
|
targetdir = r"..\build\LunaTranslator"
|
||||||
|
downlevel = r"C:\Windows\system32\downlevel"
|
||||||
|
src = py37Pathlocal = (
|
||||||
|
os.environ["LOCALAPPDATA"] + r"\Programs\Python\Python37" + "\\"
|
||||||
|
)
|
||||||
|
py37Path = "C:\\hostedtoolcache\\windows\\Python\\3.7.9\\x64\\python.exe"
|
||||||
|
py37Pathlocal = os.environ["LOCALAPPDATA"] + r"\Programs\Python\Python37\python.exe"
|
||||||
|
webviewappendix = r"Lib\site-packages\webviewpy\platform\win32\x64\webview.dll"
|
||||||
|
if os.path.exists(py37Path) == False:
|
||||||
|
py37Path = py37Pathlocal
|
||||||
|
py37Pathwebview = os.path.join(os.path.dirname(py37Path), webviewappendix)
|
||||||
|
|
||||||
|
saveopen = builtins.open
|
||||||
|
|
||||||
|
|
||||||
|
def __open(*arg, **kwarg):
|
||||||
|
if len(arg) > 1:
|
||||||
|
mode = arg[1]
|
||||||
|
else:
|
||||||
|
mode = ""
|
||||||
|
if "b" not in mode:
|
||||||
|
kwarg["encoding"] = "utf8"
|
||||||
|
return saveopen(*arg, **kwarg)
|
||||||
|
|
||||||
|
|
||||||
|
builtins.open = __open
|
||||||
|
|
||||||
|
|
||||||
|
def get_import_table(file_path):
|
||||||
|
pe = pefile.PE(file_path)
|
||||||
|
import_dlls = []
|
||||||
|
if hasattr(pe, "DIRECTORY_ENTRY_IMPORT"):
|
||||||
|
for entry in pe.DIRECTORY_ENTRY_IMPORT:
|
||||||
|
dll_name = entry.dll.decode("utf-8")
|
||||||
|
import_dlls.append(dll_name)
|
||||||
|
return import_dlls
|
||||||
|
|
||||||
|
|
||||||
|
def get_dependencies(filename):
|
||||||
|
finder = modulefinder.ModuleFinder()
|
||||||
|
|
||||||
|
finder.run_script(filename)
|
||||||
|
|
||||||
|
dependencies = []
|
||||||
|
for name, module in finder.modules.items():
|
||||||
|
if module.__file__ is not None:
|
||||||
|
dependencies.append(module.__file__)
|
||||||
|
|
||||||
|
return dependencies
|
||||||
|
|
||||||
|
|
||||||
|
def copycheck(src, tgt):
|
||||||
|
if not os.path.exists(src):
|
||||||
|
return
|
||||||
|
if src.lower().endswith("_ssl.pyd"):
|
||||||
|
return
|
||||||
|
if not os.path.exists(tgt):
|
||||||
|
os.makedirs(tgt, exist_ok=True)
|
||||||
|
if os.path.isdir(src):
|
||||||
|
tgt = os.path.join(tgt, os.path.basename(src))
|
||||||
|
if os.path.exists(tgt):
|
||||||
|
shutil.rmtree(tgt)
|
||||||
|
shutil.copytree(src, tgt)
|
||||||
|
return
|
||||||
|
shutil.copy(src, tgt)
|
||||||
|
|
||||||
|
|
||||||
|
if os.path.exists(targetdir):
|
||||||
|
shutil.rmtree(targetdir)
|
||||||
|
copycheck(os.path.join(launch, "LunaTranslator.exe"), targetdir)
|
||||||
|
copycheck(os.path.join(launch, "LunaTranslator_admin.exe"), targetdir)
|
||||||
|
copycheck(os.path.join(launch, "LunaTranslator_debug.exe"), targetdir)
|
||||||
|
copycheck("./LunaTranslator", targetdir)
|
||||||
|
copycheck(r".\files", targetdir)
|
||||||
|
try:
|
||||||
|
shutil.rmtree(rf"{targetdir}\files\plugins\{baddll}")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
shutil.copy(r"..\LICENSE", targetdir)
|
||||||
|
shutil.copy(py37Pathwebview, rf"{targetdir}\files\plugins\{gooddll}")
|
||||||
|
|
||||||
|
all_dependencies = set()
|
||||||
|
for _d, _, _fs in os.walk("./LunaTranslator"):
|
||||||
|
for f in _fs:
|
||||||
|
if not f.endswith(".py"):
|
||||||
|
continue
|
||||||
|
base = os.path.basename(_d)
|
||||||
|
if base in [
|
||||||
|
"tts",
|
||||||
|
"transoptimi",
|
||||||
|
"translator",
|
||||||
|
"scalemethod",
|
||||||
|
"ocrengines",
|
||||||
|
"winhttp",
|
||||||
|
"libcurl",
|
||||||
|
"network",
|
||||||
|
"hiraparse",
|
||||||
|
"cishu",
|
||||||
|
"textoutput",
|
||||||
|
]:
|
||||||
|
continue
|
||||||
|
print(base, f)
|
||||||
|
got = get_dependencies(os.path.join(_d, f))
|
||||||
|
all_dependencies = all_dependencies.union(set(got))
|
||||||
|
|
||||||
|
for dependency in all_dependencies:
|
||||||
|
if dependency.startswith("./"):
|
||||||
|
continue
|
||||||
|
print(dependency)
|
||||||
|
end = dependency[len(src) :]
|
||||||
|
if end.lower().startswith("lib"):
|
||||||
|
end = end[4:]
|
||||||
|
if end.lower().startswith("site-packages"):
|
||||||
|
end = end[len("site-packages") + 1 :]
|
||||||
|
elif end.lower().startswith("dlls"):
|
||||||
|
end = end[5:]
|
||||||
|
tgtreal = os.path.dirname(os.path.join(tgt, end))
|
||||||
|
copycheck(dependency, tgtreal)
|
||||||
|
|
||||||
|
|
||||||
|
with open(os.path.join(tgt, "python37._pth"), "w") as ff:
|
||||||
|
ff.write(".\n..")
|
||||||
|
|
||||||
|
copycheck(os.path.join(src, "python3.dll"), tgt)
|
||||||
|
copycheck(os.path.join(src, "python37.dll"), tgt)
|
||||||
|
copycheck(os.path.join(src, "Dlls/sqlite3.dll"), tgt)
|
||||||
|
|
||||||
|
copycheck(os.path.join(src, "Lib/encodings"), os.path.join(tgt))
|
||||||
|
|
||||||
|
|
||||||
|
copycheck(rf"{downlevel}\ucrtbase.dll", tgt)
|
||||||
|
copycheck(
|
||||||
|
os.path.join(src, "Lib/site-packages/PyQt5/Qt5/bin/vcruntime140.dll"),
|
||||||
|
os.path.join(tgt),
|
||||||
|
)
|
||||||
|
copycheck(
|
||||||
|
os.path.join(src, "Lib/site-packages/PyQt5/Qt5/bin/vcruntime140_1.dll"),
|
||||||
|
os.path.join(tgt),
|
||||||
|
)
|
||||||
|
copycheck(
|
||||||
|
os.path.join(src, "Lib/site-packages/PyQt5/Qt5/bin/msvcp140.dll"), os.path.join(tgt)
|
||||||
|
)
|
||||||
|
copycheck(
|
||||||
|
os.path.join(src, "Lib/site-packages/PyQt5/Qt5/bin/Qt5/msvcp140_1.dll"),
|
||||||
|
os.path.join(tgt),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
for _ in os.listdir(os.path.join(src, "Lib/site-packages/PyQt5")):
|
||||||
|
if _.startswith("sip"):
|
||||||
|
copycheck(
|
||||||
|
os.path.join(src, "Lib/site-packages/PyQt5", _), os.path.join(tgt, "PyQt5")
|
||||||
|
)
|
||||||
|
|
||||||
|
copycheck(
|
||||||
|
os.path.join(src, "Lib/site-packages/PyQt5/Qt5/bin/Qt5Core.dll"),
|
||||||
|
os.path.join(tgt, "PyQt5/Qt5/bin"),
|
||||||
|
)
|
||||||
|
copycheck(
|
||||||
|
os.path.join(src, "Lib/site-packages/PyQt5/Qt5/bin/Qt5Gui.dll"),
|
||||||
|
os.path.join(tgt, "PyQt5/Qt5/bin"),
|
||||||
|
)
|
||||||
|
copycheck(
|
||||||
|
os.path.join(src, "Lib/site-packages/PyQt5/Qt5/bin/Qt5Widgets.dll"),
|
||||||
|
os.path.join(tgt, "PyQt5/Qt5/bin"),
|
||||||
|
)
|
||||||
|
|
||||||
|
copycheck(
|
||||||
|
os.path.join(src, "Lib/site-packages/PyQt5/Qt5/plugins/imageformats"),
|
||||||
|
os.path.join(tgt, "PyQt5/Qt5/plugins"),
|
||||||
|
)
|
||||||
|
copycheck(
|
||||||
|
os.path.join(src, "Lib/site-packages/PyQt5/Qt5/plugins/platforms/qoffscreen.dll"),
|
||||||
|
os.path.join(tgt, "PyQt5/Qt5/plugins/platforms"),
|
||||||
|
)
|
||||||
|
copycheck(
|
||||||
|
os.path.join(src, "Lib/site-packages/PyQt5/Qt5/plugins/platforms/qwindows.dll"),
|
||||||
|
os.path.join(tgt, "PyQt5/Qt5/plugins/platforms"),
|
||||||
|
)
|
||||||
|
copycheck(
|
||||||
|
os.path.join(
|
||||||
|
src, "Lib/site-packages/PyQt5/Qt5/plugins/styles/qwindowsvistastyle.dll"
|
||||||
|
),
|
||||||
|
os.path.join(tgt, "PyQt5/Qt5/plugins/styles"),
|
||||||
|
)
|
||||||
|
|
||||||
|
collect = []
|
||||||
|
for _dir, _, fs in os.walk(targetdir):
|
||||||
|
for f in fs:
|
||||||
|
collect.append(os.path.join(_dir, f))
|
||||||
|
for src in collect:
|
||||||
|
if src.endswith(".pyc") or src.endswith("Thumbs.db"):
|
||||||
|
os.remove(f)
|
||||||
|
|
||||||
|
elif src.lower().endswith(".pyd") or src.lower().endswith(".dll"):
|
||||||
|
|
||||||
|
if src.endswith("QtWidgets.pyd"):
|
||||||
|
imports = [
|
||||||
|
"api-ms-win-crt-runtime-l1-1-0.dll",
|
||||||
|
"api-ms-win-crt-heap-l1-1-0.dll",
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
imports = get_import_table(src)
|
||||||
|
print(src, imports)
|
||||||
|
if len(imports) == 0:
|
||||||
|
continue
|
||||||
|
with open(src, "rb") as ff:
|
||||||
|
bs = bytearray(ff.read())
|
||||||
|
for _dll in imports:
|
||||||
|
if _dll.lower().startswith("api-ms-win-core"):
|
||||||
|
# 其实对于api-ms-win-core-winrt-XXX实际上是到ComBase.dll之类的,不过此项目中不包含这些
|
||||||
|
_target = "kernel32.dll"
|
||||||
|
elif _dll.lower().startswith("api-ms-win-crt"):
|
||||||
|
_target = "ucrtbase.dll"
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
_dll = _dll.encode()
|
||||||
|
_target = _target.encode()
|
||||||
|
idx = bs.find(_dll)
|
||||||
|
bs[idx : idx + len(_dll)] = _target + b"\0" * (len(_dll) - len(_target))
|
||||||
|
with open(os.path.join(tgt, os.path.basename(src)), "wb") as ff:
|
||||||
|
ff.write(bs)
|
||||||
|
|
||||||
|
target = os.path.basename(targetdir)
|
||||||
|
if os.path.exists(rf"{targetdir}\..\{target}.zip"):
|
||||||
|
os.remove(rf"{targetdir}\..\{target}.zip")
|
||||||
|
if os.path.exists(rf"{targetdir}\..\{target}.7z"):
|
||||||
|
os.remove(rf"{targetdir}\..\{target}.7z")
|
||||||
|
os.system(
|
||||||
|
rf'"C:\Program Files\7-Zip\7z.exe" a -m0=Deflate -mx9 {targetdir}\..\{target}.zip {targetdir}'
|
||||||
|
)
|
||||||
|
os.system(
|
||||||
|
rf'"C:\Program Files\7-Zip\7z.exe" a -m0=LZMA2 -mx9 {targetdir}\..\{target}.7z {targetdir}'
|
||||||
|
)
|
||||||
|
|
||||||
|
with open(r"C:\Program Files\7-Zip\7z.sfx", "rb") as ff:
|
||||||
|
sfx = ff.read()
|
||||||
|
|
||||||
|
config = """
|
||||||
|
;!@Install@!UTF-8!
|
||||||
|
|
||||||
|
|
||||||
|
;!@InstallEnd@!
|
||||||
|
"""
|
||||||
|
with open(rf"{targetdir}\..\{target}.7z", "rb") as ff:
|
||||||
|
data = ff.read()
|
||||||
|
|
||||||
|
with open(rf"{targetdir}\..\{target}.exe", "wb") as ff:
|
||||||
|
ff.write(sfx)
|
||||||
|
ff.write(config.encode("utf8"))
|
||||||
|
ff.write(data)
|
21
build.py
21
build.py
@ -242,26 +242,7 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
os.chdir(rootDir + "\\LunaTranslator")
|
os.chdir(rootDir + "\\LunaTranslator")
|
||||||
|
|
||||||
cmdline=py37Path
|
|
||||||
cmdline+=' -m nuitka --standalone --assume-yes-for-downloads '
|
|
||||||
if not isdebug:
|
|
||||||
cmdline+=' --disable-console '
|
|
||||||
cmdline+=' --plugin-enable=pyqt5 '
|
|
||||||
|
|
||||||
if arch == "x86":
|
|
||||||
if isdebug:
|
|
||||||
cmdline+='--output-dir=..\\build\\x86_debug'
|
|
||||||
else:
|
|
||||||
cmdline+='--output-dir=..\\build\\x86'
|
|
||||||
else:
|
|
||||||
if isdebug:
|
|
||||||
cmdline+='--output-dir=..\\build\\x64_debug'
|
|
||||||
else:
|
|
||||||
cmdline+='--output-dir=..\\build\\x64'
|
|
||||||
cmdline+=' LunaTranslator\\LunaTranslator_main.py --windows-icon-from-ico=..\\plugins\\exec\\luna.ico '
|
|
||||||
|
|
||||||
subprocess.run(f"{py37Path} -m pip install --upgrade pip")
|
subprocess.run(f"{py37Path} -m pip install --upgrade pip")
|
||||||
subprocess.run(f"{py37Path} -m pip install -r requirements.txt")
|
subprocess.run(f"{py37Path} -m pip install -r requirements.txt")
|
||||||
subprocess.run(cmdline)
|
|
||||||
|
|
||||||
subprocess.run(f'python pack.py {int(arch == "x86")} {int(isdebug)}')
|
subprocess.run(f'{py37Path} retrieval.py {int(arch == "x86")}')
|
@ -1,13 +1,13 @@
|
|||||||
|
|
||||||
project(LUNA)
|
project(LUNA)
|
||||||
|
|
||||||
|
option(PYSTAND_CONSOLE "Build PyStand as a console application." OFF)
|
||||||
add_executable(LunaTranslator luna.cpp luna.rc)
|
|
||||||
#target_link_options(LunaTranslator PRIVATE /MANIFESTUAC:level="asInvoker")
|
|
||||||
|
|
||||||
add_executable(LunaTranslator_admin luna.cpp luna.rc)
|
# sources
|
||||||
set_target_properties(LunaTranslator_admin PROPERTIES LINK_FLAGS " /MANIFESTUAC:\"level='requireAdministrator' uiAccess='false'\" ")
|
set(sources PyStand.cpp luna.rc)
|
||||||
|
|
||||||
#target_link_options(LunaTranslator_admin PRIVATE /MANIFESTUAC:level="requireAdministrator")
|
add_executable(LunaTranslator_debug ${sources})
|
||||||
#这个仅在visualstdio下管用,vscode cmake不管用了。
|
target_compile_definitions(LunaTranslator_debug PRIVATE PYSTAND_CONSOLE)
|
||||||
|
add_executable(LunaTranslator WIN32 ${sources})
|
||||||
|
add_executable(LunaTranslator_admin WIN32 ${sources})
|
||||||
|
set_target_properties(LunaTranslator_admin PROPERTIES LINK_FLAGS " /MANIFESTUAC:\"level='requireAdministrator' uiAccess='false'\" ")
|
414
plugins/exec/PyStand.cpp
Normal file
414
plugins/exec/PyStand.cpp
Normal file
@ -0,0 +1,414 @@
|
|||||||
|
//=====================================================================
|
||||||
|
//
|
||||||
|
// PyStand.cpp -
|
||||||
|
//
|
||||||
|
// Created by skywind on 2022/02/03
|
||||||
|
// Last Modified: 2023/03/17 20:06
|
||||||
|
//
|
||||||
|
//=====================================================================
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <shlwapi.h>
|
||||||
|
#include <string>
|
||||||
|
#include <string.h>
|
||||||
|
#include <winbase.h>
|
||||||
|
#include <wincon.h>
|
||||||
|
|
||||||
|
#include "PyStand.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma comment(lib, "shlwapi.lib")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// dtor
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
PyStand::~PyStand()
|
||||||
|
{
|
||||||
|
FreeLibrary(_hDLL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// ctor
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
PyStand::PyStand(const wchar_t *runtime)
|
||||||
|
{
|
||||||
|
_hDLL = NULL;
|
||||||
|
_Py_Main = NULL;
|
||||||
|
if (CheckEnviron(runtime) == false) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (LoadPython() == false) {
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// ctor for ansi
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
PyStand::PyStand(const char *runtime)
|
||||||
|
{
|
||||||
|
_hDLL = NULL;
|
||||||
|
_Py_Main = NULL;
|
||||||
|
std::wstring rtp = Ansi2Unicode(runtime);
|
||||||
|
if (CheckEnviron(rtp.c_str()) == false) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (LoadPython() == false) {
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// char to wchar_t
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
std::wstring PyStand::Ansi2Unicode(const char *text)
|
||||||
|
{
|
||||||
|
int len = (int)strlen(text);
|
||||||
|
std::wstring wide;
|
||||||
|
int require = MultiByteToWideChar(CP_ACP, 0, text, len, NULL, 0);
|
||||||
|
if (require > 0) {
|
||||||
|
wide.resize(require);
|
||||||
|
MultiByteToWideChar(CP_ACP, 0, text, len, &wide[0], require);
|
||||||
|
}
|
||||||
|
return wide;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// init: _args, _argv, _cwd, _pystand, _home, _runtime,
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
bool PyStand::CheckEnviron(const wchar_t *rtp)
|
||||||
|
{
|
||||||
|
// init: _args, _argv
|
||||||
|
LPWSTR *argvw;
|
||||||
|
int argc;
|
||||||
|
_args = GetCommandLineW();
|
||||||
|
argvw = CommandLineToArgvW(_args.c_str(), &argc);
|
||||||
|
if (argvw == NULL) {
|
||||||
|
MessageBoxA(NULL, "Error in CommandLineToArgvW()", "ERROR", MB_OK);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_argv.resize(argc);
|
||||||
|
for (int i = 0; i < argc; i++) {
|
||||||
|
_argv[i] = argvw[i];
|
||||||
|
}
|
||||||
|
LocalFree(argvw);
|
||||||
|
|
||||||
|
// init: _cwd (current working directory)
|
||||||
|
wchar_t path[MAX_PATH + 10];
|
||||||
|
GetCurrentDirectoryW(MAX_PATH + 1, path);
|
||||||
|
_cwd = path;
|
||||||
|
|
||||||
|
// init: _pystand (full path of PyStand.exe)
|
||||||
|
GetModuleFileNameW(NULL, path, MAX_PATH + 1);
|
||||||
|
#if 0
|
||||||
|
wsprintf(path, L"e:\\github\\tools\\pystand\\pystand.exe");
|
||||||
|
#endif
|
||||||
|
_pystand = path;
|
||||||
|
|
||||||
|
// init: _home
|
||||||
|
int size = (int)wcslen(path);
|
||||||
|
for (; size > 0; size--) {
|
||||||
|
if (path[size - 1] == L'/') break;
|
||||||
|
if (path[size - 1] == L'\\') break;
|
||||||
|
}
|
||||||
|
path[size] = 0;
|
||||||
|
SetCurrentDirectoryW(path);
|
||||||
|
GetCurrentDirectoryW(MAX_PATH + 1, path);
|
||||||
|
_home = path;
|
||||||
|
SetCurrentDirectoryW(_cwd.c_str());
|
||||||
|
|
||||||
|
// init: _runtime (embedded python directory)
|
||||||
|
bool abspath = false;
|
||||||
|
if (wcslen(rtp) >= 3) {
|
||||||
|
if (rtp[1] == L':') {
|
||||||
|
if (rtp[2] == L'/' || rtp[2] == L'\\')
|
||||||
|
abspath = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (abspath == false) {
|
||||||
|
_runtime = _home + L"\\" + rtp;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_runtime = rtp;
|
||||||
|
}
|
||||||
|
GetFullPathNameW(_runtime.c_str(), MAX_PATH + 1, path, NULL);
|
||||||
|
_runtime = path;
|
||||||
|
|
||||||
|
// check home
|
||||||
|
std::wstring check = _runtime;
|
||||||
|
if (!PathFileExistsW(check.c_str())) {
|
||||||
|
std::wstring msg = L"Missing embedded Python3 in:\n" + check;
|
||||||
|
MessageBoxW(NULL, msg.c_str(), L"ERROR", MB_OK);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check python3.dll
|
||||||
|
std::wstring check2 = _runtime + L"\\python3.dll";
|
||||||
|
if (!PathFileExistsW(check2.c_str())) {
|
||||||
|
std::wstring msg = L"Missing python3.dll in:\r\n" + check;
|
||||||
|
MessageBoxW(NULL, msg.c_str(), L"ERROR", MB_OK);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup environment
|
||||||
|
SetEnvironmentVariableW(L"PYSTAND", _pystand.c_str());
|
||||||
|
SetEnvironmentVariableW(L"PYSTAND_HOME", _home.c_str());
|
||||||
|
SetEnvironmentVariableW(L"PYSTAND_RUNTIME", _runtime.c_str());
|
||||||
|
|
||||||
|
// unnecessary to init PYSTAND_SCRIPT here.
|
||||||
|
#if 0
|
||||||
|
SetEnvironmentVariableW(L"PYSTAND_SCRIPT", _script.c_str());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
wprintf(L"%s - %s\n", _pystand.c_str(), path);
|
||||||
|
MessageBoxW(NULL, _pystand.c_str(), _home.c_str(), MB_OK);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// load python
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
bool PyStand::LoadPython()
|
||||||
|
{
|
||||||
|
std::wstring runtime = _runtime;
|
||||||
|
std::wstring previous;
|
||||||
|
|
||||||
|
// save current directory
|
||||||
|
wchar_t path[MAX_PATH + 10];
|
||||||
|
GetCurrentDirectoryW(MAX_PATH + 1, path);
|
||||||
|
previous = path;
|
||||||
|
|
||||||
|
// python dll must be load under "runtime"
|
||||||
|
SetCurrentDirectoryW(runtime.c_str());
|
||||||
|
// LoadLibrary
|
||||||
|
_hDLL = (HINSTANCE)LoadLibraryA("python3.dll");
|
||||||
|
if (_hDLL) {
|
||||||
|
_Py_Main = (t_Py_Main)GetProcAddress(_hDLL, "Py_Main");
|
||||||
|
}
|
||||||
|
|
||||||
|
// restore director
|
||||||
|
SetCurrentDirectoryW(previous.c_str());
|
||||||
|
|
||||||
|
if (_hDLL == NULL) {
|
||||||
|
std::wstring msg = L"Cannot load python3.dll from:\r\n" + runtime;
|
||||||
|
MessageBoxW(NULL, msg.c_str(), L"ERROR", MB_OK);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (_Py_Main == NULL) {
|
||||||
|
std::wstring msg = L"Cannot find Py_Main() in:\r\n";
|
||||||
|
msg += runtime + L"\\python3.dll";
|
||||||
|
MessageBoxW(NULL, msg.c_str(), L"ERROR", MB_OK);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// run string
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
int PyStand::RunString(const wchar_t *script)
|
||||||
|
{
|
||||||
|
if (_Py_Main == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int hr = 0;
|
||||||
|
int i;
|
||||||
|
_py_argv.resize(0);
|
||||||
|
// init arguments
|
||||||
|
_py_argv.push_back(_argv[0]);
|
||||||
|
_py_argv.push_back(L"-I");
|
||||||
|
_py_argv.push_back(L"-s");
|
||||||
|
_py_argv.push_back(L"-S");
|
||||||
|
_py_argv.push_back(L"-c");
|
||||||
|
_py_argv.push_back(script);
|
||||||
|
for (i = 1; i < (int)_argv.size(); i++) {
|
||||||
|
_py_argv.push_back(_argv[i]);
|
||||||
|
}
|
||||||
|
// finalize arguments
|
||||||
|
_py_args.resize(0);
|
||||||
|
for (i = 0; i < (int)_py_argv.size(); i++) {
|
||||||
|
_py_args.push_back((wchar_t*)_py_argv[i].c_str());
|
||||||
|
}
|
||||||
|
hr = _Py_Main((int)_py_args.size(), &_py_args[0]);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// run ansi string
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
int PyStand::RunString(const char *script)
|
||||||
|
{
|
||||||
|
std::wstring text = Ansi2Unicode(script);
|
||||||
|
return RunString(text.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// static init script
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
#ifndef PYSTAND_STATIC_NAME
|
||||||
|
#define PYSTAND_STATIC_NAME "LunaTranslator\\LunaTranslator_main.py"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// LoadScript()
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
int PyStand::DetectScript()
|
||||||
|
{
|
||||||
|
// init: _script (init script like PyStand.int or PyStand.py)
|
||||||
|
int size = (int)_pystand.size() - 1;
|
||||||
|
for (; size >= 0; size--) {
|
||||||
|
if (_pystand[size] == L'.') break;
|
||||||
|
}
|
||||||
|
if (size < 0) size = (int)_pystand.size();
|
||||||
|
std::wstring main = _pystand.substr(0, size);
|
||||||
|
std::vector<const wchar_t*> exts;
|
||||||
|
std::vector<std::wstring> scripts;
|
||||||
|
_script.clear();
|
||||||
|
#if !(PYSTAND_DISABLE_STATIC)
|
||||||
|
std::wstring test;
|
||||||
|
test = _home + L"\\" + Ansi2Unicode(PYSTAND_STATIC_NAME);
|
||||||
|
if (PathFileExistsW(test.c_str())) {
|
||||||
|
_script = test;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (_script.empty()) {
|
||||||
|
exts.push_back(L".int");
|
||||||
|
exts.push_back(L".py");
|
||||||
|
exts.push_back(L".pyw");
|
||||||
|
for (int i = 0; i < (int)exts.size(); i++) {
|
||||||
|
std::wstring test = main + exts[i];
|
||||||
|
scripts.push_back(test);
|
||||||
|
if (PathFileExistsW(test.c_str())) {
|
||||||
|
_script = test;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_script.size() == 0) {
|
||||||
|
std::wstring msg = L"Can't find either of:\r\n";
|
||||||
|
for (int j = 0; j < (int)scripts.size(); j++) {
|
||||||
|
msg += scripts[j] + L"\r\n";
|
||||||
|
}
|
||||||
|
MessageBoxW(NULL, msg.c_str(), L"ERROR", MB_OK);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SetEnvironmentVariableW(L"PYSTAND_SCRIPT", _script.c_str());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// init script
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
const char *init_script =
|
||||||
|
"import sys\n"
|
||||||
|
"import os\n"
|
||||||
|
"PYSTAND = os.environ['PYSTAND']\n"
|
||||||
|
"PYSTAND_HOME = os.environ['PYSTAND_HOME']\n"
|
||||||
|
"PYSTAND_RUNTIME = os.environ['PYSTAND_RUNTIME']\n"
|
||||||
|
"PYSTAND_SCRIPT = os.environ['PYSTAND_SCRIPT']\n"
|
||||||
|
"sys.path_origin = [n for n in sys.path]\n"
|
||||||
|
"sys.PYSTAND = PYSTAND\n"
|
||||||
|
"sys.PYSTAND_HOME = PYSTAND_HOME\n"
|
||||||
|
"sys.PYSTAND_SCRIPT = PYSTAND_SCRIPT\n"
|
||||||
|
"def MessageBox(msg, info = 'Message'):\n"
|
||||||
|
" import ctypes\n"
|
||||||
|
" ctypes.windll.user32.MessageBoxW(None, str(msg), str(info), 0)\n"
|
||||||
|
" return 0\n"
|
||||||
|
"os.MessageBox = MessageBox\n"
|
||||||
|
#ifndef PYSTAND_CONSOLE
|
||||||
|
"try:\n"
|
||||||
|
" fd = os.open('CONOUT$', os.O_RDWR | os.O_BINARY)\n"
|
||||||
|
" fp = os.fdopen(fd, 'w')\n"
|
||||||
|
" sys.stdout = fp\n"
|
||||||
|
" sys.stderr = fp\n"
|
||||||
|
" attached = True\n"
|
||||||
|
"except Exception as e:\n"
|
||||||
|
" fp = open(os.devnull, 'w')\n"
|
||||||
|
" sys.stdout = fp\n"
|
||||||
|
" sys.stderr = fp\n"
|
||||||
|
" attached = False\n"
|
||||||
|
#endif
|
||||||
|
"sys.argv = [PYSTAND_SCRIPT] + sys.argv[1:]\n"
|
||||||
|
"text = open(PYSTAND_SCRIPT, 'rb').read()\n"
|
||||||
|
"environ = {'__file__': PYSTAND_SCRIPT, '__name__': '__main__'}\n"
|
||||||
|
"environ['__package__'] = None\n"
|
||||||
|
#ifndef PYSTAND_CONSOLE
|
||||||
|
"try:\n"
|
||||||
|
" code = compile(text, PYSTAND_SCRIPT, 'exec')\n"
|
||||||
|
" exec(code, environ)\n"
|
||||||
|
"except Exception:\n"
|
||||||
|
" if attached:\n"
|
||||||
|
" raise\n"
|
||||||
|
" import traceback, io\n"
|
||||||
|
" sio = io.StringIO()\n"
|
||||||
|
" traceback.print_exc(file = sio)\n"
|
||||||
|
" os.MessageBox(sio.getvalue(), 'Error')\n"
|
||||||
|
#else
|
||||||
|
"code = compile(text, PYSTAND_SCRIPT, 'exec')\n"
|
||||||
|
"exec(code, environ)\n"
|
||||||
|
#endif
|
||||||
|
"";
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// main
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
//! flag: -static
|
||||||
|
//! src:
|
||||||
|
//! link: stdc++, shlwapi, resource.o
|
||||||
|
//! prebuild: windres resource.rc -o resource.o
|
||||||
|
//! mode: win
|
||||||
|
//! int: objs
|
||||||
|
|
||||||
|
#ifdef PYSTAND_CONSOLE
|
||||||
|
int main()
|
||||||
|
#else
|
||||||
|
int WINAPI
|
||||||
|
WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR args, int show)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
PyStand ps("LunaTranslator\\runtime");
|
||||||
|
if (ps.DetectScript() != 0) {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
#ifndef PYSTAND_CONSOLE
|
||||||
|
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
|
||||||
|
freopen("CONOUT$", "w", stdout);
|
||||||
|
freopen("CONOUT$", "w", stderr);
|
||||||
|
int fd = _fileno(stdout);
|
||||||
|
if (fd >= 0) {
|
||||||
|
std::string fn = std::to_string(fd);
|
||||||
|
SetEnvironmentVariableA("PYSTAND_STDOUT", fn.c_str());
|
||||||
|
}
|
||||||
|
fd = _fileno(stdin);
|
||||||
|
if (fd >= 0) {
|
||||||
|
std::string fn = std::to_string(fd);
|
||||||
|
SetEnvironmentVariableA("PYSTAND_STDIN", fn.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
int hr = ps.RunString(init_script);
|
||||||
|
// printf("finalize\n");
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
61
plugins/exec/PyStand.h
Normal file
61
plugins/exec/PyStand.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
//=====================================================================
|
||||||
|
//
|
||||||
|
// PyStand.h -
|
||||||
|
//
|
||||||
|
// Created by skywind on 2022/02/03
|
||||||
|
// Last Modified: 2022/02/03 23:39:52
|
||||||
|
//
|
||||||
|
//=====================================================================
|
||||||
|
#ifndef _PYSTAND_H_
|
||||||
|
#define _PYSTAND_H_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <shlwapi.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// PyStand
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
class PyStand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~PyStand();
|
||||||
|
PyStand(const wchar_t *runtime);
|
||||||
|
PyStand(const char *runtime);
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::wstring Ansi2Unicode(const char *text);
|
||||||
|
|
||||||
|
int RunString(const wchar_t *script);
|
||||||
|
int RunString(const char *script);
|
||||||
|
|
||||||
|
int DetectScript();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool CheckEnviron(const wchar_t *rtp);
|
||||||
|
bool LoadPython();
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
typedef int (*t_Py_Main)(int argc, wchar_t **argv);
|
||||||
|
t_Py_Main _Py_Main;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
HINSTANCE _hDLL;
|
||||||
|
std::wstring _cwd; // current working directory
|
||||||
|
std::wstring _args; // arguments
|
||||||
|
std::wstring _pystand; // absolute path of pystand
|
||||||
|
std::wstring _runtime; // absolute path of embedded python runtime
|
||||||
|
std::wstring _home; // home directory of PyStand.exe
|
||||||
|
std::wstring _script; // init script like PyStand.int or PyStand.py
|
||||||
|
std::vector<std::wstring> _argv;
|
||||||
|
std::vector<std::wstring> _py_argv;
|
||||||
|
std::vector<wchar_t*> _py_args;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1,22 +0,0 @@
|
|||||||
#include <windows.h>
|
|
||||||
#include <string>
|
|
||||||
#include <filesystem>
|
|
||||||
#pragma comment(linker, "/subsystem:windows /entry:mainCRTStartup")
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
TCHAR szPath[MAX_PATH];
|
|
||||||
GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath));
|
|
||||||
std::wstring moduleName = szPath;
|
|
||||||
auto currpath = moduleName.substr(0, moduleName.rfind(L'\\'));
|
|
||||||
auto exe = currpath + L".\\LunaTranslator\\LunaTranslator_main.exe";
|
|
||||||
if (!std::filesystem::exists(exe))
|
|
||||||
{
|
|
||||||
MessageBoxW(0, (L"Can't find LunaTranslator\\LunaTranslator_main.exe, please download again."), L"Error", 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
STARTUPINFO _1 = {};
|
|
||||||
PROCESS_INFORMATION _2;
|
|
||||||
CreateProcessW(exe.c_str(), NULL, NULL, NULL, FALSE, 0, NULL, currpath.c_str(), &_1, &_2);
|
|
||||||
return 0;
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user