6

Edit: With the help of Qt support, I have solved how to automate these 2 parts of the Qt enterprise installer. below is the script calls.

I'm trying to silent install Qt 5.5.1 Enterprise on Windows 8.1 and Windows 10, using the "--script" switch to call a javascript that automates the UI, but can't seem to read all the elements in the UI to read it.

I have 2 controller pages that work differently than the standard Qt installer, particularly the "CredentialsPageCallback" which requires a checkbox to be checked before calling "gui.clickButton(buttons.NextButton);" It also props a new callback page called "ManualLicensePageCallback" which has no documentation on it at all. Here's the script I'm writing. I need the Checkbox name on the Credentials page, and the two "Line edit" calls on the Manual page:

// Emacs mode hint: -*- mode: JavaScript -*-

function Controller() {
    //installer.autoRejectMessageBoxes();
    installer.installationFinished.connect(function() {
    gui.clickButton(buttons.NextButton);
    })
}

Controller.prototype.WelcomePageCallback = function() {
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.CredentialsPageCallback = function() {
    gui.pageWidgetByObjectName("CredentialsPage").enterManuallyCheckBox.click();
    gui.clickButton(buttons.NextButton);    
}

Controller.prototype.ManualLicensePageCallback = function() {
    var page = gui.pageWidgetByObjectName("ManualLicensePage");
    page.LicenseeLineEdit.setText("NAME");
    page.Qt5KeyLineEdit.setText("REG KEY");
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.IntroductionPageCallback = function() {
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.TargetDirectoryPageCallback = function() {
    gui.currentPageWidget().TargetDirectoryLineEdit.setText("C:\\Path\\To\\Install");
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.ComponentSelectionPageCallback = function() {
    var widget = gui.currentPageWidget();

    //BY DEFAULT, THE DEFAULT INSTALL METHOD IS SELECTED
    //USE THESE WIDGET CALLS TO DESELECT ANY  ITEMS

    //widget.deselectAll();
    //widget.deselectComponent("qt.55.win64_msvc2013_64");
    //widget.deselectComponent("qt.55.qt3d");
    //widget.deselectComponent("qt.55.qtquick1");
    //widget.deselectComponent("qt.55.qtwebengine");
    //widget.deselectComponent("qt.55.qtquickcontrols");
    //widget.deselectComponent("qt.55.qtscript");
    //widget.deselectComponent("qt.55.qtcanvas3d");
    //widget.deselectComponent("qt.55.qtlocation");

    //widget.deselectComponent("qt.tools");
    //widget.deselectComponent("qt.extras");
    //widget.deselectComponent("qt.enterpriseaddons");

    gui.clickButton(buttons.NextButton);
}

Controller.prototype.LicenseAgreementPageCallback = function() {
    gui.currentPageWidget().AcceptLicenseRadioButton.setChecked(true);
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.StartMenuDirectoryPageCallback = function() {
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.ReadyForInstallationPageCallback = function() {
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.FinishedPageCallback = function() {
    var checkBoxForm = gui.currentPageWidget().LaunchQtCreatorCheckBoxForm
    if (checkBoxForm && checkBoxForm.launchQtCreatorCheckBox) {
        checkBoxForm.launchQtCreatorCheckBox.checked = false;
    }
    gui.clickButton(buttons.FinishButton);
}
sinsuren
  • 1,745
  • 2
  • 23
  • 26
Kevinsyel
  • 143
  • 1
  • 9
  • 2
    I find Qt's installers to be more trouble than they are worth. If you're using Qt in any sort of a professional capacity, you should compile it yourself; installing it then is simply decompressing an archive and perhaps adding an element to PATH. – Kuba hasn't forgotten Monica Mar 02 '16 at 13:40
  • I agree, but the task I'm attempting to do is take the enterprise installer that installs QT, and build a silent installer so that developers can spin up new development machines without issue. This includes using our registration key and autofilling elements inside the installer. Sorry if my question wasn't clear. Thanks! – Kevinsyel Mar 02 '16 at 18:45
  • 1
    A Qt "install", when it's pre-built, amounts to decompressing an archive (optionally relocating paths if you've moved it). You can optionally add it to the PATH. There's literally nothing else to be done. If you wish, you can use whatever means to install it on your machine (via installer, rebuild, etc.) and then simply zip it up and deploy that way. As long as you deploy to the same path on every machine, you don't need to do anything else. Involving an "installer" to further redistribute such a setup is superfluous. – Kuba hasn't forgotten Monica Mar 02 '16 at 19:11
  • 1
    There's some documentation you can use to find UI elements, but it's not comprehensive. You can go here http://download.qt.io/online/qtsdkrepository to find an Updates.XML file -- Select platform->subplatform->qt->Updates.XML It mentions an installscript.qs -- if there are existing install scripts (probably in source) you may be able to find some helpful into there. – kayleeFrye_onDeck Mar 02 '16 at 23:49
  • Kuba Ober- This works great for standard installs of Qt, but for the enterprise version, where do the license details get stored? I know there's some stored in C:\Users\\AppData\Roaming\Qt, but I believe if also sets up a registry key, which is why we're attempting to automate the installer versus packaging a decompressed install and copying it to another machine. Thanks for your input. – Kevinsyel Mar 03 '16 at 00:51
  • The benefit of using the installer with the silent scripts becomes clearer in 5.9, where for Windows, the installer now includes all possible Windows binary packages. It also gives the option to install the debugger finally. But with all the different pre-built binary options, a single installer with multiple installer scripts becomes more useful than individualized dumb self-extracting installers or just archives, especially when multiple teams on multiple platforms are consuming the installer and scripts for various purposes. Also, my old comment seems no longer valid. – kayleeFrye_onDeck Jun 16 '17 at 20:51
  • Added an actual working answer for this question, haha! Trial-by-install... – kayleeFrye_onDeck Jun 16 '17 at 23:14

1 Answers1

4

I found one of the Windows label values in a file called components.xml while searching through XML files in a 5.8 installation. After viewing all of it, it looked like that file is generated by your choices at installation. So I did a full installation of the latest released Qt (5.9.0) with the exception of Source, which I knew was "qt.59.src" for the component label after experimenting with some of them.

In regards to direct UI element inspection to get these, I tried out all the UI-inspection tools from the gui-inspect-tool repo, but none of them panned out. UISpy.exe provided the most info but was fairly unstable. It looks like Qt does not propagate its component names to the "Name" field for easy use with WinAPIs and native Windows UI inspectors. All the "Name" fields were either empty strings or returning errors from all the UI-inspection tools.

After installation, you can open components.xml at your base qt installation.

Then search for the term Prebuilt for the whole file. Each hit will take you to a description field, and two lines above that is the name field you need. With 5.9, I think there is one exception for that in regards to the pre-built binaries, and that's (Deprecated) Qt Script.

Here's an example of one of the packages in components.xml:

<Package>
        <Name>qt.59.android_armv7</Name>
        <Title>Android ARMv7</Title>
        <Description>Qt 5.9.0 Prebuilt Components for Android ARMv7</Description>
        <Version>5.9.0-0</Version>
        <LastUpdateDate></LastUpdateDate>
        <InstallDate>2017-06-16</InstallDate>
        <Size>145381493</Size>
        <Dependencies>qt.tools.qtcreator,qt.59.doc,qt.59.examples,qt.tools.win32_mingw530</Dependencies>
        <Checkable>true</Checkable>
    </Package>

That <Name> of qt.59.android_armv7 is the actual component string to use for your QS file, e.g.,

Controller.prototype.ComponentSelectionPageCallback = function() {
    var widget = gui.currentPageWidget();

    widget.selectAll();

    widget.deselectComponent("qt.59.android_armv7");

    gui.clickButton(buttons.NextButton);
}

To save some people some time who might be using 5.9 or an installer with a similar structure, here's all the label names for different pre-built platforms:

Android ARMv7: "qt.59.android_armv7"
Android x86: "qt.59.android_x86"
MinGW 5.3.0 32 bit: "qt.59.win32_mingw53"
msvc2017 64-bit: "qt.59.win64_msvc2017_64"
msvc2015 32-bit: "qt.59.win32_msvc2015"
msvc2015 64-bit: "qt.59.win64_msvc2015_64"
msvc2013 64-bit: "qt.59.win64_msvc2013_64"
UWP x64 (MSVC2015): "qt.59.win64_msvc2015_winrt_x64"
UWP x64 (MSVC2017): "qt.59.win64_msvc2017_winrt_x64"
UWP x86 (MSVC2015): "qt.59.win64_msvc2015_winrt_x86"
UWP x86 (MSVC2017): "qt.59.win64_msvc2017_winrt_x86"
UWP armv7 (MSVC2015): "qt.59.win64_msvc2015_winrt_armv7"
UWP armv7 (MSVC2017): "qt.59.win64_msvc2017_winrt_armv7"

As a further courtesy, here is a dump of all of the components. Some of these are actually dependencies for the component you choose, so your mileage will vary:

"qt"
"qt.59"
"qt.59.android_armv7"
"qt.59.android_x86"
"qt.59.doc"
"qt.59.doc.qtcharts"
"qt.59.doc.qtdatavis3d"
"qt.59.doc.qtnetworkauth"
"qt.59.doc.qtpurchasing"
"qt.59.doc.qtremoteobjects"
"qt.59.doc.qtscript"
"qt.59.doc.qtspeech"
"qt.59.doc.qtvirtualkeyboard"
"qt.59.doc.qtwebengine"
"qt.59.examples"
"qt.59.examples.qtcharts"
"qt.59.examples.qtdatavis3d"
"qt.59.examples.qtnetworkauth"
"qt.59.examples.qtpurchasing"
"qt.59.examples.qtremoteobjects"
"qt.59.examples.qtscript"
"qt.59.examples.qtspeech"
"qt.59.examples.qtvirtualkeyboard"
"qt.59.examples.qtwebengine"
"qt.59.qtcharts"
"qt.59.qtcharts.android_armv7"
"qt.59.qtcharts.android_x86"
"qt.59.qtcharts.win32_mingw53"
"qt.59.qtcharts.win32_msvc2015"
"qt.59.qtcharts.win64_msvc2013_64"
"qt.59.qtcharts.win64_msvc2015_64"
"qt.59.qtcharts.win64_msvc2015_winrt_armv7"
"qt.59.qtcharts.win64_msvc2015_winrt_x64"
"qt.59.qtcharts.win64_msvc2015_winrt_x86"
"qt.59.qtcharts.win64_msvc2017_64"
"qt.59.qtcharts.win64_msvc2017_winrt_armv7"
"qt.59.qtcharts.win64_msvc2017_winrt_x64"
"qt.59.qtcharts.win64_msvc2017_winrt_x86"
"qt.59.qtdatavis3d"
"qt.59.qtdatavis3d.android_armv7"
"qt.59.qtdatavis3d.android_x86"
"qt.59.qtdatavis3d.win32_mingw53"
"qt.59.qtdatavis3d.win32_msvc2015"
"qt.59.qtdatavis3d.win64_msvc2013_64"
"qt.59.qtdatavis3d.win64_msvc2015_64"
"qt.59.qtdatavis3d.win64_msvc2015_winrt_armv7"
"qt.59.qtdatavis3d.win64_msvc2015_winrt_x64"
"qt.59.qtdatavis3d.win64_msvc2015_winrt_x86"
"qt.59.qtdatavis3d.win64_msvc2017_64"
"qt.59.qtdatavis3d.win64_msvc2017_winrt_armv7"
"qt.59.qtdatavis3d.win64_msvc2017_winrt_x64"
"qt.59.qtdatavis3d.win64_msvc2017_winrt_x86"
"qt.59.qtnetworkauth"
"qt.59.qtnetworkauth.android_armv7"
"qt.59.qtnetworkauth.android_x86"
"qt.59.qtnetworkauth.win32_mingw53"
"qt.59.qtnetworkauth.win32_msvc2015"
"qt.59.qtnetworkauth.win64_msvc2013_64"
"qt.59.qtnetworkauth.win64_msvc2015_64"
"qt.59.qtnetworkauth.win64_msvc2015_winrt_armv7"
"qt.59.qtnetworkauth.win64_msvc2015_winrt_x64"
"qt.59.qtnetworkauth.win64_msvc2015_winrt_x86"
"qt.59.qtnetworkauth.win64_msvc2017_64"
"qt.59.qtnetworkauth.win64_msvc2017_winrt_armv7"
"qt.59.qtnetworkauth.win64_msvc2017_winrt_x64"
"qt.59.qtnetworkauth.win64_msvc2017_winrt_x86"
"qt.59.qtpurchasing"
"qt.59.qtpurchasing.android_armv7"
"qt.59.qtpurchasing.android_x86"
"qt.59.qtpurchasing.win32_mingw53"
"qt.59.qtpurchasing.win32_msvc2015"
"qt.59.qtpurchasing.win64_msvc2013_64"
"qt.59.qtpurchasing.win64_msvc2015_64"
"qt.59.qtpurchasing.win64_msvc2015_winrt_armv7"
"qt.59.qtpurchasing.win64_msvc2015_winrt_x64"
"qt.59.qtpurchasing.win64_msvc2015_winrt_x86"
"qt.59.qtpurchasing.win64_msvc2017_64"
"qt.59.qtpurchasing.win64_msvc2017_winrt_armv7"
"qt.59.qtpurchasing.win64_msvc2017_winrt_x64"
"qt.59.qtpurchasing.win64_msvc2017_winrt_x86"
"qt.59.qtremoteobjects"
"qt.59.qtremoteobjects.android_armv7"
"qt.59.qtremoteobjects.android_x86"
"qt.59.qtremoteobjects.win32_mingw53"
"qt.59.qtremoteobjects.win32_msvc2015"
"qt.59.qtremoteobjects.win64_msvc2013_64"
"qt.59.qtremoteobjects.win64_msvc2015_64"
"qt.59.qtremoteobjects.win64_msvc2015_winrt_armv7"
"qt.59.qtremoteobjects.win64_msvc2015_winrt_x64"
"qt.59.qtremoteobjects.win64_msvc2015_winrt_x86"
"qt.59.qtremoteobjects.win64_msvc2017_64"
"qt.59.qtremoteobjects.win64_msvc2017_winrt_armv7"
"qt.59.qtremoteobjects.win64_msvc2017_winrt_x64"
"qt.59.qtremoteobjects.win64_msvc2017_winrt_x86"
"qt.59.qtscript"
"qt.59.qtscript.android_armv7"
"qt.59.qtscript.android_x86"
"qt.59.qtscript.win32_mingw53"
"qt.59.qtscript.win32_msvc2015"
"qt.59.qtscript.win64_msvc2013_64"
"qt.59.qtscript.win64_msvc2015_64"
"qt.59.qtscript.win64_msvc2017_64"
"qt.59.qtspeech"
"qt.59.qtspeech.android_armv7"
"qt.59.qtspeech.android_x86"
"qt.59.qtspeech.win32_mingw53"
"qt.59.qtspeech.win32_msvc2015"
"qt.59.qtspeech.win64_msvc2013_64"
"qt.59.qtspeech.win64_msvc2015_64"
"qt.59.qtspeech.win64_msvc2017_64"
"qt.59.qtvirtualkeyboard"
"qt.59.qtvirtualkeyboard.win32_mingw53"
"qt.59.qtvirtualkeyboard.win32_msvc2015"
"qt.59.qtvirtualkeyboard.win64_msvc2013_64"
"qt.59.qtvirtualkeyboard.win64_msvc2015_64"
"qt.59.qtvirtualkeyboard.win64_msvc2017_64"
"qt.59.qtwebengine"
"qt.59.qtwebengine.win32_msvc2015"
"qt.59.qtwebengine.win64_msvc2015_64"
"qt.59.qtwebengine.win64_msvc2017_64"
"qt.59.src"
"qt.59.win32_mingw53"
"qt.59.win32_msvc2015"
"qt.59.win64_msvc2013_64"
"qt.59.win64_msvc2015_64"
"qt.59.win64_msvc2015_winrt_armv7"
"qt.59.win64_msvc2015_winrt_x64"
"qt.59.win64_msvc2015_winrt_x86"
"qt.59.win64_msvc2017_64"
"qt.59.win64_msvc2017_winrt_armv7"
"qt.59.win64_msvc2017_winrt_x64"
"qt.59.win64_msvc2017_winrt_x86"
"qt.enterpriseaddons"
"qt.enterpriseaddons.qtquickcompiler"
"qt.enterpriseaddons.qtquickcompiler.doc"
"qt.enterpriseaddons.qtquickcompiler.qt59.android_armv7"
"qt.enterpriseaddons.qtquickcompiler.qt59.android_x86"
"qt.enterpriseaddons.qtquickcompiler.qt59.win32_mingw53"
"qt.enterpriseaddons.qtquickcompiler.qt59.win32_msvc2015"
"qt.enterpriseaddons.qtquickcompiler.qt59.win64_msvc2013_64"
"qt.enterpriseaddons.qtquickcompiler.qt59.win64_msvc2015_64"
"qt.enterpriseaddons.qtquickcompiler.qt59.win64_msvc2015_winrt_armv7"
"qt.enterpriseaddons.qtquickcompiler.qt59.win64_msvc2015_winrt_x64"
"qt.enterpriseaddons.qtquickcompiler.qt59.win64_msvc2015_winrt_x86"
"qt.enterpriseaddons.qtquickcompiler.qt59.win64_msvc2017_64"
"qt.enterpriseaddons.qtquickcompiler.qt59.win64_msvc2017_winrt_armv7"
"qt.enterpriseaddons.qtquickcompiler.qt59.win64_msvc2017_winrt_x64"
"qt.enterpriseaddons.qtquickcompiler.qt59.win64_msvc2017_winrt_x86"
"qt.installer.changelog"
"qt.license.automotive"
"qt.license.embedded"
"qt.license.enterprise"
"qt.license.python"
"qt.tools"
"qt.tools.perl"
"qt.tools.qtcreator"
"qt.tools.qtcreator.enterprise.plugins"
"qt.tools.qtcreatorcdbext"
"qt.tools.vcredist_msvc2015_x64"
"qt.tools.vcredist_msvc2015_x86"
"qt.tools.win32_mingw530"

As a full function, this is the actual function I use for our Windows installations:

Controller.prototype.ComponentSelectionPageCallback = function() {
    var widget = gui.currentPageWidget();

    widget.selectAll();

    widget.deselectComponent("qt.59.android_x86");
    widget.deselectComponent("qt.59.android_armv7");
    widget.deselectComponent("qt.59.win32_mingw53");
    widget.deselectComponent("qt.59.win64_msvc2013_64");
    widget.deselectComponent("qt.59.win64_msvc2017_winrt_armv7");
    widget.deselectComponent("qt.59.win64_msvc2015_winrt_armv7");
    widget.deselectComponent("qt.59.src");
    widget.deselectComponent("qt.tools.perl");
    widget.deselectComponent("qt.tools.win32_mingw530");

    gui.clickButton(buttons.NextButton);
}

If you want to see how to make one of these scripts from scratch, you should check out this answer to get started: https://stackoverflow.com/a/34032216/3543437

Update for 5.9.1

Change all the strings that have 59. to 591. for 5.9.1; if you use the same script for 5.9.0 as 5.9.1, it will try to install everything due to not deselecting the correct components.

Update for 5.9.3

It looks like they thankfully stuck to the same convention of 5.9.1, so just change 59 to 593; I'm assuming this will also be the case for 5.9.2, and any subsequent 5.9 releases.

kayleeFrye_onDeck
  • 6,648
  • 5
  • 69
  • 80