"AllUsers" not working if set programmatically in QtIFW
-
I manage the installation of a small application of mine on Windows using QtIFW.
The following snippet of XML in the
package.xmlof one of the installed components sets a link to the application on the Desktop:<Operations> ... <Operation name="CreateShortcut"> <Argument>@TargetDir@\LBChronoRace.exe</Argument> <Argument>@DesktopDir@\LBChronoRace.lnk</Argument> <Argument>workingDirectory=@TargetDir@</Argument> <Argument>iconPath=@TargetDir@\LBChronoRace.exe</Argument> <Argument>iconId=0</Argument> <!--<Argument>description="Start LBChronoRace"</Argument>--> </Operation> ... </Operations>The link is installed on the Desktop folder of the user that is installing the application.
I would like the link to be installed in the Desktop directory common to all users. To achieve this I tried running the installer by adding
AllUsers=trueto its command line. And it worked.Since this is not feasible for those who will download and install the application (they will not be developers and will install with a simple double click), I tried setting
AllUsers=trueprogrammatically in the IFW control script:function Controller() { installer.setValue("AllUsers", "true"); }But it doesn't work and the link keeps being created in the user's Desktop folder instead of the common folder.
I have evidence that the variable is set. Infact in the last page of the installer the value is reported as true by the following snippet:
Controller.prototype.FinishedPageCallback = function() { var allUsers = installer.value("AllUsers"); var desktopDir = installer.value("DesktopDir"); var page = gui.pageWidgetByObjectName("FinishedPage"); if (page) { var msg = "AllUsers = " + allUsers + "\nDesktopDir = " + desktopDir; page.MessageLabel.setText(msg); } };Looking at the
addDynamicPredefinedVariables()function ofpackagemanagercoredata.cpp(in the IFW sources) I notice this:QString desktop; if (m_variables.value(QLatin1String("AllUsers")) == scTrue) { desktop = system.value(QLatin1String("Common Desktop")).toString(); } else { desktop = user.value(QLatin1String("Desktop")).toString(); } addNewVariable(QLatin1String("DesktopDir"), replaceWindowsEnvironmentVariables(desktop));So I don't understand why there should be a difference between when the variable set in the environment and when it is set programmatically.
I also tried the same on the component script
installscript.qs:function Component() { } Component.prototype.createOperations = function() { /* Set the variabile BEFORE operations creation */ installer.setValue("AllUsers", "true"); /* Go on with standard operations */ component.createOperations(); };with both
<Script>installscript.qs</Script>and
<Script postLoad="true">installscript.qs</Script>but without any change in the installer behaviour.
-
I manage the installation of a small application of mine on Windows using QtIFW.
The following snippet of XML in the
package.xmlof one of the installed components sets a link to the application on the Desktop:<Operations> ... <Operation name="CreateShortcut"> <Argument>@TargetDir@\LBChronoRace.exe</Argument> <Argument>@DesktopDir@\LBChronoRace.lnk</Argument> <Argument>workingDirectory=@TargetDir@</Argument> <Argument>iconPath=@TargetDir@\LBChronoRace.exe</Argument> <Argument>iconId=0</Argument> <!--<Argument>description="Start LBChronoRace"</Argument>--> </Operation> ... </Operations>The link is installed on the Desktop folder of the user that is installing the application.
I would like the link to be installed in the Desktop directory common to all users. To achieve this I tried running the installer by adding
AllUsers=trueto its command line. And it worked.Since this is not feasible for those who will download and install the application (they will not be developers and will install with a simple double click), I tried setting
AllUsers=trueprogrammatically in the IFW control script:function Controller() { installer.setValue("AllUsers", "true"); }But it doesn't work and the link keeps being created in the user's Desktop folder instead of the common folder.
I have evidence that the variable is set. Infact in the last page of the installer the value is reported as true by the following snippet:
Controller.prototype.FinishedPageCallback = function() { var allUsers = installer.value("AllUsers"); var desktopDir = installer.value("DesktopDir"); var page = gui.pageWidgetByObjectName("FinishedPage"); if (page) { var msg = "AllUsers = " + allUsers + "\nDesktopDir = " + desktopDir; page.MessageLabel.setText(msg); } };Looking at the
addDynamicPredefinedVariables()function ofpackagemanagercoredata.cpp(in the IFW sources) I notice this:QString desktop; if (m_variables.value(QLatin1String("AllUsers")) == scTrue) { desktop = system.value(QLatin1String("Common Desktop")).toString(); } else { desktop = user.value(QLatin1String("Desktop")).toString(); } addNewVariable(QLatin1String("DesktopDir"), replaceWindowsEnvironmentVariables(desktop));So I don't understand why there should be a difference between when the variable set in the environment and when it is set programmatically.
I also tried the same on the component script
installscript.qs:function Component() { } Component.prototype.createOperations = function() { /* Set the variabile BEFORE operations creation */ installer.setValue("AllUsers", "true"); /* Go on with standard operations */ component.createOperations(); };with both
<Script>installscript.qs</Script>and
<Script postLoad="true">installscript.qs</Script>but without any change in the installer behaviour.
@Flinco
I have never used installer and know nothing about it, but doesn't stop me trying to help :)One obvious way your findings could occur would be if the
addDynamicPredefinedVariables()were called only before yourinstaller.setValue("AllUsers", "true"). IF the only important bit is theaddNewVariable(QLatin1String("DesktopDir"), ...)maybe try settinginstaller.setValue("DesktopDir", desiredPath)instead and see if that has any effect? And can you ensure yourfunction Controller()is indeed called? -
@JonB, I replaced
installer.setValue("AllUsers", "true");withinstaller.setValue("DesktopDir", installer.toNativeSeparators("C:/Users/Public/Desktop"));in the body offunction Controller().This ensured that
function Controller()is called (I don't know when...), but it certainly gets called since this time the link was created inC:\Users\Public\Desktop(that is exactly where I expect).Now, I think this may just be a workaround, since IMHO relying on the fact that the
"Common Desktop"directory is always and will always beC:\Users\Public\Desktopis wrong. -
@JonB, I replaced
installer.setValue("AllUsers", "true");withinstaller.setValue("DesktopDir", installer.toNativeSeparators("C:/Users/Public/Desktop"));in the body offunction Controller().This ensured that
function Controller()is called (I don't know when...), but it certainly gets called since this time the link was created inC:\Users\Public\Desktop(that is exactly where I expect).Now, I think this may just be a workaround, since IMHO relying on the fact that the
"Common Desktop"directory is always and will always beC:\Users\Public\Desktopis wrong.@Flinco
This was supposed to be a test to see if you can get something working. Obviously you should not pass a literal string but something based onsystem.value(QLatin1String("Common Desktop"))andreplaceWindowsEnvironmentVariables(desktop), per the code you showed. -
@JonB, thank you for your valuable suggestions.
I found out that this piece of code is working and can be an acceptable workaround:function Controller() { var commonDesktopPath = system.value(QLatin1String("Common Desktop")); installer.setValue("DesktopDir", installer.toNativeSeparators(commonDesktopPath)) } -
@JonB, thank you for your valuable suggestions.
I found out that this piece of code is working and can be an acceptable workaround:function Controller() { var commonDesktopPath = system.value(QLatin1String("Common Desktop")); installer.setValue("DesktopDir", installer.toNativeSeparators(commonDesktopPath)) }@Flinco
That was indeed the kind of thing I was suggesting. For unknown reason it appears that theifinif (m_variables.value(QLatin1String("AllUsers")) == scTrue) { desktop = system.value(QLatin1String("Common Desktop")).toString(); } else { desktop = user.value(QLatin1String("Desktop")).toString(); }reacts as desired when you pass
AllUsers=trueon command line but not whenfunction Controller() { installer.setValue("AllUsers", "true"); }Perhaps this is "too late" (or even "too early") for the call to
addDynamicPredefinedVariables(). Your new code/this "workaround" does the code for the choice ofsystem.value(QLatin1String("Common Desktop"))unconditionally without relying onm_variables.value(QLatin1String("AllUsers")) == scTrue(btw, I do not know whethersetValue("AllUsers", "true")actually sets a value which equalsscTrue).