如何使用cx_Freeze为相同脚本使用不同参数创建多个msi安装程序?

huangapple go评论114阅读模式
英文:

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() 函数时,它可以创建第一个安装程序而没有任何问题,但在第二次迭代时出现错误:

  1. running install_exe
  2. copying build\exe.win32-3.7\frozen_application_license.txt -> build\bdist.win32\msi
  3. error: could not create 'build\bdist.win32\msi\frozen_application_license.txt': No such file or directory

我已经尝试在每次迭代后删除 build 目录或修改 argv,但那不起作用。

以下是运行并出现错误的应用程序的最小示例。我只需运行 python setup.py 即可创建安装程序:

setup.py

  1. import sys
  2. from cx_Freeze import setup, Executable
  3. sys.argv.append("bdist_msi")
  4. programs = { # 名称和 GUID 对
  5. "hello": "{6ae7456f-2761-43a2-8a23-1a3dd284e947}",
  6. "world": "{494d5953-651d-41c5-a6ef-9156c96987a1}",
  7. }
  8. for program, GUID in programs.items():
  9. setup(
  10. name=f"Hello-{program}",
  11. version="1.0",
  12. executables=[Executable("hello.py")],
  13. options={
  14. "bdist_msi": {
  15. "initial_target_dir": f"C:\{program}",
  16. "upgrade_code": GUID,
  17. },
  18. },
  19. )

hello.py

  1. from tkinter import *
  2. from tkinter import ttk
  3. root = Tk()
  4. frm = ttk.Frame(root, padding=10)
  5. frm.grid()
  6. ttk.Label(frm, text="Hello World!").grid(column=0, row=0)
  7. ttk.Button(frm, text="Quit", command=root.destroy).grid(column=1, row=0)
  8. 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:

  1. running install_exe
  2. copying build\exe.win32-3.7\frozen_application_license.txt -> build\bdist.win32\msi
  3. 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

  1. import sys
  2. from cx_Freeze import setup, Executable
  3. sys.argv.append("bdist_msi")
  4. programs = { # name, GUID pairs
  5. "hello": "{6ae7456f-2761-43a2-8a23-1a3dd284e947}",
  6. "world": "{494d5953-651d-41c5-a6ef-9156c96987a1}",
  7. }
  8. for program, GUID in programs.items():
  9. setup(
  10. name=f"Hello-{program}",
  11. version="1.0",
  12. executables=[Executable("hello.py")],
  13. options={
  14. "bdist_msi": {
  15. "initial_target_dir": f"C:\{program}",
  16. "upgrade_code": GUID,
  17. },
  18. },
  19. )

hello.py

  1. from tkinter import *
  2. from tkinter import ttk
  3. root = Tk()
  4. frm = ttk.Frame(root, padding=10)
  5. frm.grid()
  6. ttk.Label(frm, text="Hello World!").grid(column=0, row=0)
  7. ttk.Button(frm, text="Quit", command=root.destroy).grid(column=1, row=0)
  8. 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

  1. import os
  2. import sys
  3. from cx_Freeze import setup, Executable
  4. sys.argv.append("bdist_msi")
  5. program = os.environ['PROGRAM']
  6. GUID = os.environ['GUID']
  7. setup(
  8. name=f"Hello-{program}",
  9. version="1.0",
  10. executables=[Executable("hello.py")],
  11. options={
  12. "bdist_msi": {
  13. "initial_target_dir": f"C:\{program}",
  14. "upgrade_code": GUID,
  15. },
  16. },
  17. )

build.sh / build.cmd

  1. # Customer 1
  2. PROGRAM = "hello"
  3. GUID = "6ae7456f-2761-43a2-8a23-1a3dd284e947"
  4. python setup.py
  5. # Maybe clean build output
  6. # Customer 2
  7. PROGRAM = "world"
  8. GUID = "494d5953-651d-41c5-a6ef-9156c96987a1"
  9. 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

  1. import os
  2. import sys
  3. from cx_Freeze import setup, Executable
  4. sys.argv.append("bdist_msi")
  5. program = os.environ['PROGRAM']
  6. GUID = os.environ['GUID']
  7. setup(
  8. name=f"Hello-{program}",
  9. version="1.0",
  10. executables=[Executable("hello.py")],
  11. options={
  12. "bdist_msi": {
  13. "initial_target_dir": f"C:\{program}",
  14. "upgrade_code": GUID,
  15. },
  16. },
  17. )

build.sh / build.cmd

  1. # Customer 1
  2. PROGRAM = "hello"
  3. GUID = "6ae7456f-2761-43a2-8a23-1a3dd284e947"
  4. python setup.py
  5. # Maybe clean build output
  6. # Customer 2
  7. PROGRAM = "world"
  8. GUID = "494d5953-651d-41c5-a6ef-9156c96987a1"
  9. python setup.py

With this structure you could split further and for example have one CI/CD pipeline for each customer.

huangapple
  • 本文由 发表于 2023年2月27日 01:02:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/75573612.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定