我终于找到了一个可行的解决方案。
你需要三件事来实现这一点:
- 一个组件脚本,
- 目标目录页面的自定义 UI,以及
- 自动单击卸载程序的控制器脚本。
我现在将逐字列出对我有用的内容(以及我的项目特定内容)。我的组件被称为Atlas4500 Tuner
配置.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Installer>
<Name>Atlas4500 Tuner</Name>
<Version>1.0.0</Version>
<Title>Atlas4500 Tuner Installer</Title>
<Publisher>EF Johnson Technologies</Publisher>
<StartMenuDir>EF Johnson</StartMenuDir>
<TargetDir>C:\Program Files (x86)\EF Johnson\Atlas4500 Tuner</TargetDir>
</Installer>
包/Atlas4500 Tuner/meta/package.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Package>
<DisplayName>Atlas4500Tuner</DisplayName>
<Description>Install the Atlas4500 Tuner</Description>
<Version>1.0.0</Version>
<ReleaseDate></ReleaseDate>
<Default>true</Default>
<Required>true</Required>
<Script>installscript.qs</Script>
<UserInterfaces>
<UserInterface>targetwidget.ui</UserInterface>
</UserInterfaces>
</Package>
自定义组件脚本包/Atlas4500 Tuner/meta/installscript.qs:
var targetDirectoryPage = null;
function Component()
{
installer.gainAdminRights();
component.loaded.connect(this, this.installerLoaded);
}
Component.prototype.createOperations = function()
{
// Add the desktop and start menu shortcuts.
component.createOperations();
component.addOperation("CreateShortcut",
"@TargetDir@/Atlas4500Tuner.exe",
"@DesktopDir@/Atlas4500 Tuner.lnk",
"workingDirectory=@TargetDir@");
component.addOperation("CreateShortcut",
"@TargetDir@/Atlas4500Tuner.exe",
"@StartMenuDir@/Atlas4500 Tuner.lnk",
"workingDirectory=@TargetDir@");
}
Component.prototype.installerLoaded = function()
{
installer.setDefaultPageVisible(QInstaller.TargetDirectory, false);
installer.addWizardPage(component, "TargetWidget", QInstaller.TargetDirectory);
targetDirectoryPage = gui.pageWidgetByObjectName("DynamicTargetWidget");
targetDirectoryPage.windowTitle = "Choose Installation Directory";
targetDirectoryPage.description.setText("Please select where the Atlas4500 Tuner will be installed:");
targetDirectoryPage.targetDirectory.textChanged.connect(this, this.targetDirectoryChanged);
targetDirectoryPage.targetDirectory.setText(installer.value("TargetDir"));
targetDirectoryPage.targetChooser.released.connect(this, this.targetChooserClicked);
gui.pageById(QInstaller.ComponentSelection).entered.connect(this, this.componentSelectionPageEntered);
}
Component.prototype.targetChooserClicked = function()
{
var dir = QFileDialog.getExistingDirectory("", targetDirectoryPage.targetDirectory.text);
targetDirectoryPage.targetDirectory.setText(dir);
}
Component.prototype.targetDirectoryChanged = function()
{
var dir = targetDirectoryPage.targetDirectory.text;
if (installer.fileExists(dir) && installer.fileExists(dir + "/maintenancetool.exe")) {
targetDirectoryPage.warning.setText("<p style=\"color: red\">Existing installation detected and will be overwritten.</p>");
}
else if (installer.fileExists(dir)) {
targetDirectoryPage.warning.setText("<p style=\"color: red\">Installing in existing directory. It will be wiped on uninstallation.</p>");
}
else {
targetDirectoryPage.warning.setText("");
}
installer.setValue("TargetDir", dir);
}
Component.prototype.componentSelectionPageEntered = function()
{
var dir = installer.value("TargetDir");
if (installer.fileExists(dir) && installer.fileExists(dir + "/maintenancetool.exe")) {
installer.execute(dir + "/maintenancetool.exe", "--script=" + dir + "/scripts/auto_uninstall.qs");
}
}
自定义目标目录 widget packages/Atlas4500 Tuner/meta/targetwidget.ui:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TargetWidget</class>
<widget class="QWidget" name="TargetWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>491</width>
<height>190</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>491</width>
<height>190</height>
</size>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="description">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="targetDirectory">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="targetChooser">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="warning">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>122</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
包/Atlas4500 Tuner/data/scripts/auto_uninstall.qs:
// Controller script to pass to the uninstaller to get it to run automatically.
// It's passed to the maintenance tool during installation if there is already an
// installation present with: <target dir>/maintenancetool.exe --script=<target dir>/scripts/auto_uninstall.qs.
// This is required so that the user doesn't have to see/deal with the uninstaller in the middle of
// an installation.
function Controller()
{
gui.clickButton(buttons.NextButton);
gui.clickButton(buttons.NextButton);
installer.uninstallationFinished.connect(this, this.uninstallationFinished);
}
Controller.prototype.uninstallationFinished = function()
{
gui.clickButton(buttons.NextButton);
}
Controller.prototype.FinishedPageCallback = function()
{
gui.clickButton(buttons.FinishButton);
}
这里的想法是检测当前目录中是否有安装,如果有,则使用只需单击它的控制器脚本在该目录中运行维护工具。
请注意,我将控制器脚本放在作为实际组件数据一部分的脚本目录中。如果您有多个组件,您可能会做一些更清洁的事情,但这就是我正在使用的。
您应该能够自己复制这些文件,只需调整字符串以使其工作。