【问题标题】:Inno Setup PyInstaller Auto-UpdateInno Setup PyInstaller 自动更新
【发布时间】:2015-07-23 23:51:27
【问题描述】:

我正在尝试实现自动更新功能,因此我正在以编程方式下载 update_myprog.exe(使用 Inno Setup 创建),然后我想立即关闭该程序并运行 update_myprog.exe。目前我正在使用 subprocess.Popen() 运行它,但由于某种原因,当 update_myprog.exe 运行时,我收到错误:“安装程序无法自动关闭所有应用程序。建议您使用以下文件关闭所有应用程序在继续之前需要由安装程序更新。”。当我自己(不是通过原始程序)运行 update_myprog.exe 时,它​​工作得很好。

所以,我想知道,这是我的 Python、Inno Setup 还是其他什么问题?

以下是我的问题的简化版本,仅提取相关代码。

这是我的python代码(autoupdate.py):

import wx
import subprocess
import win32process
import tempfile

class Main(wx.Frame):
    def __init__(self,*args,**kwargs):
        wx.Frame.__init__(self,*args,**kwargs)
        self.SetTitle('MyProg v1')
        self.updatebutton=wx.Button(self,label='Update')
        self.updatebutton.Bind(wx.EVT_BUTTON,self.update)
    def update(self,event):
        canupdate=True
        if(canupdate):
            tempdir=tempfile.mkdtemp()
            fname=os.path.join(tempdir,'update_myprog.exe')
            proc = subprocess.Popen('"update_myprog.exe" /SP- /silent /noicons /nocancel /password="pw"', creationflags=win32process.DETACHED_PROCESS,shell=True)
            self.Destroy()
            sys.exit()

app = wx.App(False)
Main(parent=None).Show(True)
app.MainLoop()

然后我编译它:

pyinstaller "autoupdate.py" --distpath="make\dist" --workpath="make\build"

然后我使用以下 Inno 安装脚本制作了安装程序 (update_myprog.exe):

[Setup]
AppId={{7FBA93BE-7DC4-4114-91DF-DD524A078F63}
AppName=My Program
AppVersion=1
AppPublisher=My Company, Inc.
AppPublisherURL=http://www.example.com/
AppSupportURL=http://www.example.com/
AppUpdatesURL=http://www.example.com/
DefaultDirName={pf}\My Program
DefaultGroupName=My Program
AllowNoIcons=yes
OutputDir=make/Installer
OutputBaseFilename=update_myprog
Password=pw
Compression=lzma
SolidCompression=yes

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked

[Files]
Source: "C:\Python27\My Projects\Test Update\make\dist\autoupdate\autoupdate2.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\Python27\My Projects\Test Update\make\dist\autoupdate\*"; DestDir: "{app}";

[Icons]
Name: "{group}\My Program"; Filename: "{app}\autoupdate.exe"
Name: "{commondesktop}\My Program"; Filename: "{app}\autoupdate.exe"; Tasks: desktopicon

[Run]
Filename: "{app}\autoupdate.exe"; Description: "{cm:LaunchProgram,My Program}"; Flags: nowait postinstall

然后我运行安装程序(工作正常),并将安装程序复制到它安装到的目录中。然后我运行我的程序,然后单击按钮,它给了我一个错误。为什么?

如果其他人可以在他们的计算机上执行上述步骤,这可能会对我有所帮助,如果他们有同样的问题,请告诉我。感谢所有帮助。

老问题:

所以,我基本上和Spawning a non-child process in python 有同样的问题,但对于 Windows。

我正在尝试实现自动更新功能,因此我正在以编程方式下载 update_myprog.exe(使用 Inno Setup 创建),然后我想立即关闭该程序并运行 update_myprog.exe。目前我正在使用 subprocess.Popen() 运行它,但它似乎仍然是原始程序的子程序,因此无法覆盖原始程序的 exe 文件来更新它。

os.system 是我正在寻找的,还是有其他解决方案?

【问题讨论】:

    标签: python process inno-setup


    【解决方案1】:

    如果你想完全分离可以使用的进程:

    from win32process import DETACHED_PROCESS
    from subprocess import Popen
    Popen(["python","xyz.py"],creationflags=DETACHED_PROCESS,shell=True).pid
    

    更新

    使用临时目录编译它可能会导致它自己的小噩梦,但这是另一个问题,天知道 wx 在这里的表现如何。确保 download 实际上正在完成并尝试使用 execfile(filename) 而不是 Popen。如果没有运气,请尝试以下操作:

    from subprocess import Popen, CREATE_NEW_CONSOLE,CREATE_NEW_PROCESS_GROUP
    Popen(["python", 'xyz.py'],shell = True | CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE)
    

    如果做不到这一点,请重新发布问题并让其他人看看。抱歉,我无法提供更多帮助。让我知道你最后是怎么猜到的。

    【讨论】:

    • 我试过了,可惜没用。也许我误解了我的问题...现在编辑问题。
    • 我知道下载正在完成,因为运行下载的“update_myprog.exe”成功。据我了解(来自文档),execfile 仅用于运行 python 代码,我想运行一个可执行文件。我会选择你的另一个选项,尽管在文档中,它说如果设置了 CREATE_NEW_CONSOLE,则忽略 CREATE_NEW_PROCESS_GROUP,如果 shell=True,则默认设置 CREATE_NEW_CONSOLE。非常感谢您的建议。
    【解决方案2】:

    一年多前,我使用 Inno Setup 和 PyInstaller 实现了自动更新。 您需要在子流程之前调用self.destroy()。这样在你调用 Inno 之后,你可以立即退出。您还可以使用 /FORCECLOSEAPPLICATIONS 标志,以便 Inno-Setup 可以在 sys.exit() 不够快的情况下关闭您的程序。

    【讨论】: