卸载之前通过cx_freeze bdist_msi创建的先前安装的MSI

5
我经常使用 cx_freeze 将我的 Python 源代码与所有依赖项打包,并通过 distutils bdist_msi 扩展创建 msi 安装程序包。
唯一的问题是,当我尝试重新安装新创建的 msi Windows 安装程序时,没有卸载之前的版本。卸载程序会记录所有先前卸载的软件版本,导致注册表和卸载程序信息混乱。
是否可能检测到以前安装的软件版本并自动卸载它,而不安装新版本?
我知道 NSIS,通过其 Python 绑定创建安装程序,可以轻松解决我上面提到的问题。不幸的是,此时我不想使用 Python 提供的 distutils 之外的任何东西。
2个回答

10
在 cx_Freeze 中,bdist_msi 有一个选项 upgrade-code文档中描述为:

定义创建的软件包的升级代码;这用于强制删除先前使用相同升级代码创建的任何软件包,然后再安装此软件包

要指定它,您需要将其传递给 setup() 调用,就像这样:
options = {"bdist_msi": {"upgrade-code":"..."}}

(我总是忘记选项名称中应该使用 - 还是 _,如果这样是错误的,请尝试将其更改为 upgrade_code

微软表示升级代码应该是 GUID(随机生成的代码)。


1
+1 很棒的回答。关于修复 Windows 卸载出现问题的提示:打开路径 C:\Windows\assembly,并按下 Public Key Token 列标题 以排序。然后查找您的 MSI 公共令牌号码(即未被删除的 MSI 安装程序的号码)并删除这些令牌条目。在糟糕的卸载之后执行此操作将允许正确的重新安装/升级,减少混乱的注册表和卸载程序信息。干杯!*P.S. 这是如何修复 ATi Catalyst 驱动程序和 CCC 面板更新出现问题的方法。 - arttronics
确实是个很好的答案。奇怪的是,我之前也尝试过使用升级代码,但不知道如何使用它。现在有了你提到微软网站上应该是一个随机GUID的参考,这就说得通了。明天早上我会第一时间尝试并更新结果。 - Abhijit
我阅读了链接并进行了操作,但我无法进行安装以删除旧版本并安装新版本。这是我的 setup.py http://codepaste.net/fkzojh ,您能否解释更多,如何更改产品或包ID以安装在旧包上而不是新包上? - alireza
@alireza.m:... 只是一个占位符。你应该生成一个随机的 GUID 放在那里。即使这样,它只会替换之前的版本,如果它具有相同的 GUID,所以你不能用它来删除已经存在的版本,而在此之前你想到了这个方法。 - Thomas K
@ThomasK 谢谢您的回答,但是是否有任何方法可以创建 MSI 包,以便在存在旧版本时用新版本替换旧版本? - alireza
@alireza.m:如果在发布旧版本之前没有计划,我不知道有什么简洁的方法。可能可以编写并嵌入一些说明以删除旧版本,但这可能比它的价值更麻烦。 - Thomas K

5

托马斯K的答案接近,但在我的情况下并不完全准确。经过一些尝试和错误,我发现GUID需要用花括号括起来:

bdist_msi_options = {
    "upgrade_code": "{96a85bac-52af-4019-9e94-3afcc9e1ad0c}"
    }

这些选项需要与“build_exe”选项一起传递(一些在线示例使用其他名称来表示这些参数,但我发现只有bdist_msi有效):

setup(  # name, version, description, etc...
        options={"build_exe": build_exe_options, # defined elsewhere
                 "bdist_msi": bdist_msi_options},
        executables=[Executable("run.py",
                                base="win32GUI",
                                shortcutName="My Program name",
                                shortcutDir='ProgramMenuFolder')])

使用这段代码,在我的情况下,以前的安装程序被正确卸载并从“添加/删除程序”列表中删除。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接