【问题标题】:Qt Installer Framework Offline Update - how?Qt Installer Framework 离线更新 - 如何?
【发布时间】:2014-02-18 18:40:43
【问题描述】:

我已经能够为我的软件创建安装。但是,我不知道如何创建另一个可以更新以前安装的安装程序。

我已经更新了组件版本、软件版本和发布日期,但每当我在预装软件的文件夹上运行第二次安装时 - 我收到 The folder you selected already exists and contains an installation. Chose different target for installation.

非常欢迎任何有关如何使用 Qt 安装程序框架更新现有安装的提示!

【问题讨论】:

    标签: qt installation qif qt-installer


    【解决方案1】:

    我也遇到了同样的问题。所以我下载了最新的快照并研究了样本。特别是一个非常有帮助的:dynamicpage

    当用户选择现有位置时,我没有成功向用户显示弹出警告,因此我找到了解决方法:相反,所选目录下会显示一个红色标签。

    这并不是逐个组件更新的真正解决方案,但您将能够继续安装过程。

    首先,我们需要替换默认页面“TargetDirectory”。

    在文件installerscript.qs,这是你需要添加的:

    // Constructor
    function Component()
    {
        component.loaded.connect(this, Component.prototype.installerLoaded);
        installer.setDefaultPageVisible(QInstaller.TargetDirectory, false);
    }
    
    // Utility function like QString QDir::toNativeSeparators(const QString & pathName) [static]
    var Dir = new function () {
        this.toNativeSparator = function (path) {
            if (installer.value("os") == "win")
                return path.replace(/\//g, '\\');
            return path;
        }
    };
    
    // Called as soon as the component was loaded
    Component.prototype.installerLoaded = function()
    {
        if (installer.addWizardPage(component, "TargetWidget", QInstaller.TargetDirectory)) {
            var widget = gui.pageWidgetByObjectName("DynamicTargetWidget");
            if (widget != null) {
                widget.targetDirectory.textChanged.connect(this, Component.prototype.targetChanged);
                widget.targetChooser.clicked.connect(this, Component.prototype.chooseTarget);
    
                widget.windowTitle = "Installation Folder";
                widget.targetDirectory.text = Dir.toNativeSparator(installer.value("TargetDir"));
            }
        }
    }
    
    // Callback when one is clicking on the button to select where to install your application
    Component.prototype.chooseTarget = function () {
        var widget = gui.pageWidgetByObjectName("DynamicTargetWidget");
        if (widget != null) {
            var newTarget = QFileDialog.getExistingDirectory("Choose your target directory.", widget.targetDirectory.text);
            if (newTarget != "") {
                widget.targetDirectory.text = Dir.toNativeSparator(newTarget);
            }
        }
    }
    
    Component.prototype.targetChanged = function (text) {
        var widget = gui.pageWidgetByObjectName("DynamicTargetWidget");
        if (widget != null) {
            if (text != "") {
                widget.complete = true;
                installer.setValue("TargetDir", text);
                if (installer.fileExists(text + "/components.xml")) {
                    var warning = "<font color='red'>" + qsTr("A previous installation exists in this folder. If you wish to continue, everything will be overwritten.") + "</font>";
                    widget.labelOverwrite.text = warning;
                } else {
                    widget.labelOverwrite.text = "";
                }
                return;
            }
            widget.complete = false;
        }
    }
    

    在 targetwidget.ui 文件中

    这实际上不是真正的 .ui 文件,仅用于说明目的。在这个文件的末尾,我添加了一个名为labelOverwrite 的空QLabel。文字在targetChanged回调中填充了红色消息。

    <widget class="QWidget" name="TargetWidget">
      <layout class="QVBoxLayout" name="verticalLayout">
        <item>
          <widget class="QLabel" name="label">
           <property name="text">
            <string>Please specify the folder where Miam-Player will be installed.</string>
           </property>
          </widget>
        </item>
        <item>
          <layout class="QHBoxLayout" name="horizontalLayout">
           <item>
            <widget class="QLineEdit" name="targetDirectory"/>
           </item>
           <item>
            <widget class="QToolButton" name="targetChooser"/>
           </item>
          </layout>
        </item>
        <item>
          <widget class="QLabel" name="labelOverwrite"/>
        </item>
      </layout>
    </widget>
    

    最后别忘了修改你现有的文件 package.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <Package>
        <DisplayName>Miam-Player</DisplayName>
        <Description>Miam-Player is the main program. It is required and cannot be unselected.</Description>
        <Name>org.miamplayer.core</Name>
        <Script>installscript.qs</Script>
        ...
        <UserInterfaces>
            <UserInterface>targetwidget.ui</UserInterface>
        </UserInterfaces>
    </Package>
    

    【讨论】:

    • 这真的更新了吗?或者它只是安装到同一个目录中。例如,您是否在添加/删除程序中为该程序添加了两个条目?
    • @altendky:你是对的,似乎在添加/删除程序中添加了 2 个条目。此外,在卸载第一个之后,当您尝试卸载第二个时,您会出现“发生错误:可能该项目已卸载”,这是正确的,并且该项目从列表中删除。最好的方法是替换(或更新版本号)条目。
    • Qt IFW 有在线更新确实让我感到惊讶,但我似乎无法找到一种方法来简单地使用新安装程序更新现有安装......我想我只需要去结帐 NSIS,看看它是否可以做到这一点。
    【解决方案2】:

    Matthieu 的答案是正确的,此外,如果您想要一个问题对话框,请在 installerscript.qs 中使用此功能:

    Component.prototype.targetChanged = function (text)
    {
        var widget = gui.currentPageWidget(); // get the current wizard page
        var install = false;
    
        if (widget != null)
        {
            if (text != "")
            {
                if (installer.fileExists(text + "/components.xml"))
                {
                    var result = QMessageBox.question("quit.question", "Installer", "Do you want to overwrite previous installation?",
                        QMessageBox.Yes | QMessageBox.No);
                    if (result == QMessageBox.Yes)
                    {
                       install = true;
                    }
                }
                else
                    install = true;
            }
            else
                install = false;
        }
    
        widget.complete = install;
    
        if(install)
            installer.setValue("TargetDir", text);      
    }
    

    【讨论】:

      【解决方案3】:
      Controller.prototype.TargetDirectoryPageCallback = function()
      {
          var widget = gui.currentPageWidget();
          widget.TargetDirectoryLineEdit.textChanged.connect(this, Controller.prototype.targetChanged);
          Controller.prototype.targetChanged(widget.TargetDirectoryLineEdit.text);
      }
      
      Controller.prototype.targetChanged = function (text) {
          installer.setValue("RemoveTargetDir", true);
          if (text != "" && installer.fileExists(text + "/components.xml")) {
              if(QMessageBox.question("OverwriteTargetDirectory", "Overwrite target directory", "Do you want to overwrite previous installation?", QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes) {
                  installer.setValue("RemoveTargetDir", false);
          }
      }
      

      【讨论】:

        【解决方案4】:

        这很简单。您应该执行以下操作:

        1. 如果您没有安装程序文件夹,请查看 Qt/Tools/QtInstallerFramework/3.0/examples/。对于这个例子,我复制了online 文件夹,我将其命名为my_installer_example

        2. 更新存储库以从 packages_update 上传。

        来自my_installer_example 运行:

        ./../bin/repogen --update -p packages_update/repoForUpload

        --updade 标志允许将现有存储库 (repoForUpload) 作为输入,并且只更改指定为附加参数的组件。

        1. 在服务器上传repoForUpload,由config/config.xml中的标签指定。

        2. 运行位于安装文件夹中的maintenancetool

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-02-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-01-28
          • 2016-01-25
          • 2017-01-04
          相关资源
          最近更新 更多