英文:
How can I create multiple msi installers for the same script with different parameters using cx_Freeze?
问题
我想从一个 tkinter 脚本创建多个 MSI 安装程序,每个安装程序具有不同的参数,以分发给不同的客户。我想要这样做,因为我需要更改默认的安装目录和 GUID。我正在使用最新稳定版本的 cx_Freeze
包和 Python 3.7.9
。当我在 setup.py
中运行 setup()
函数时,它可以创建第一个安装程序而没有任何问题,但在第二次迭代时出现错误:
running install_exe
copying build\exe.win32-3.7\frozen_application_license.txt -> build\bdist.win32\msi
error: could not create 'build\bdist.win32\msi\frozen_application_license.txt': No such file or directory
我已经尝试在每次迭代后删除 build
目录或修改 argv
,但那不起作用。
以下是运行并出现错误的应用程序的最小示例。我只需运行 python setup.py
即可创建安装程序:
setup.py
import sys
from cx_Freeze import setup, Executable
sys.argv.append("bdist_msi")
programs = { # 名称和 GUID 对
"hello": "{6ae7456f-2761-43a2-8a23-1a3dd284e947}",
"world": "{494d5953-651d-41c5-a6ef-9156c96987a1}",
}
for program, GUID in programs.items():
setup(
name=f"Hello-{program}",
version="1.0",
executables=[Executable("hello.py")],
options={
"bdist_msi": {
"initial_target_dir": f"C:\{program}",
"upgrade_code": GUID,
},
},
)
hello.py
from tkinter import *
from tkinter import ttk
root = Tk()
frm = ttk.Frame(root, padding=10)
frm.grid()
ttk.Label(frm, text="Hello World!").grid(column=0, row=0)
ttk.Button(frm, text="Quit", command=root.destroy).grid(column=1, row=0)
root.mainloop()
英文:
I want to create many msi installers from one tkinter script with different parameters to distribute it to different customers. I want this, because I have to change the default installation directory and GUID. I am using the latest stable version of the cx_Freeze
package and Python 3.7.9
. When I run the setup()
function inside setup.py
it creates the first installer without any problem, but at the second iteration I get an error:
running install_exe
copying build\exe.win32-3.7\frozen_application_license.txt -> build\bdist.win32\msi
error: could not create 'build\bdist.win32\msi\frozen_application_license.txt': No such file or directory
I already tried to remove the build
dir after every iteration or modify argv
after every iteration, but that won't work.
Here's a minimal example of the application to run and get an error. I just run python setup.py
to create the installers:
setup.py
import sys
from cx_Freeze import setup, Executable
sys.argv.append("bdist_msi")
programs = { # name, GUID pairs
"hello": "{6ae7456f-2761-43a2-8a23-1a3dd284e947}",
"world": "{494d5953-651d-41c5-a6ef-9156c96987a1}",
}
for program, GUID in programs.items():
setup(
name=f"Hello-{program}",
version="1.0",
executables=[Executable("hello.py")],
options={
"bdist_msi": {
"initial_target_dir": f"C:\{program}",
"upgrade_code": GUID,
},
},
)
hello.py
from tkinter import *
from tkinter import ttk
root = Tk()
frm = ttk.Frame(root, padding=10)
frm.grid()
ttk.Label(frm, text="Hello World!").grid(column=0, row=0)
ttk.Button(frm, text="Quit", command=root.destroy).grid(column=1, row=0)
root.mainloop()
答案1
得分: 1
I would recommend to solve this by running one build step for each customer using a shell/command script and parametrize with environment variables:
setup.py
import os
import sys
from cx_Freeze import setup, Executable
sys.argv.append("bdist_msi")
program = os.environ['PROGRAM']
GUID = os.environ['GUID']
setup(
name=f"Hello-{program}",
version="1.0",
executables=[Executable("hello.py")],
options={
"bdist_msi": {
"initial_target_dir": f"C:\{program}",
"upgrade_code": GUID,
},
},
)
build.sh
/ build.cmd
# Customer 1
PROGRAM = "hello"
GUID = "6ae7456f-2761-43a2-8a23-1a3dd284e947"
python setup.py
# Maybe clean build output
# Customer 2
PROGRAM = "world"
GUID = "494d5953-651d-41c5-a6ef-9156c96987a1"
python setup.py
With this structure you could split further and for example have one CI/CD pipeline for each customer.
英文:
I would recommend to solve this by running one build step for each customer using a shell/command script and parametrize with environment variables:
setup.py
import os
import sys
from cx_Freeze import setup, Executable
sys.argv.append("bdist_msi")
program = os.environ['PROGRAM']
GUID = os.environ['GUID']
setup(
name=f"Hello-{program}",
version="1.0",
executables=[Executable("hello.py")],
options={
"bdist_msi": {
"initial_target_dir": f"C:\{program}",
"upgrade_code": GUID,
},
},
)
build.sh
/ build.cmd
# Customer 1
PROGRAM = "hello"
GUID = "6ae7456f-2761-43a2-8a23-1a3dd284e947"
python setup.py
# Maybe clean build output
# Customer 2
PROGRAM = "world"
GUID = "494d5953-651d-41c5-a6ef-9156c96987a1"
python setup.py
With this structure you could split further and for example have one CI/CD pipeline for each customer.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论