"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.xml
of 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=true
to 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=true
programmatically 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.xml
of 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=true
to 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=true
programmatically 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\Desktop
is 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\Desktop
is 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 theif
inif (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=true
on 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
).