Solved Get common AppData folder
-
Hello,
I am designing a software for Windows (XP to 10 and beyond). The files are in ProgramFiles but some parameters files are in a common AppData location. The reason for this is that if the parameters files are in ProgramFiles, the users can't change them.
From NSIS installer, I set the parameters installation folder to $APPDATA. With the line SetShellVarContext all (this sets the location to "all users"), the files are in:
C:\ProgramData\MysoftWhen I launch my program, I would like to open these files to get the parameters.
I tried :
qDebug() << QStandardPaths::standardLocations(QStandardPaths::AppDataLocation);The result is the following:
("C:/Users/alecs26/AppData/Roaming/testPaths", "C:/ProgramData/testPaths", "C:/AssystMouseDev/AssystMouseDev1/build-testPaths-Desktop_Qt_5_7_1_MinGW_32bit2-Release/release", "C:/AssystMouseDev/AssystMouseDev1/build-testPaths-Desktop_Qt_5_7_1_MinGW_32bit2-Release/release/data")The location I want: "C:/ProgramData/testPaths" is there but its not the only location this function returns, how can I be sure to have only the one I want ?
[testPaths was the name of my program]Thank you very much,
Alex
-
Well the short answer is you can't be sure because the documentation says the paths can change on various conditions, but you can at least do some "safe" heuristics.
The current Windows implementation returns 4 paths : The first one is the writable location. The second is the read-only generic data location (the one you want) and the last two are the application path and application path's/data
sub-directory.QStringList locations = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation); locations.removeOne(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); locations.removeOne(QCoreApplication::applicationDirPath()); locations.removeOne(QCoreApplication::applicationDirPath() + QLatin1String("/data"));
In current implementation this code should leave you with exactly one path. To be future-proof you can iterate over the resulting list and see if any of the paths contain the file you're looking for (with QFile::exists()). Currently this loop would just do one turn. I doubt the list will grow much (or at all) in the future so this should be lightweight enough.
-
@alecs26 said in Get common AppData folder:
When I launch my program, I would like to open these files to get the parameters.
If it is just some parameters you want to store unaccessable to your user, than QSettings might be what you want. On windows, if not specified otherwise, it will store those settings in the registry.
-
@Chris-Kawa @J-Hilk
Thank you for your answers.Just to be clear, I need to open the .txt files at program start and I need the user to be able to change these parameters through a GUI in my software. So he needs "read" and "write" permissions.
What I would like is to have all users share the same parameters. My idea was then to place the parameters in C:\ProgramData\Mysoft, which is the generic data location. However, from what I understand, this is a read-only location ? The user won't be able do save his parameters there ?
If that's the case, I would have to set the location to C:/Users/alecs26/AppData/Roaming/testPaths.
The problem with that is that if I create the .txt parameters files at the software installation, it will be ok for this user but if another users logs in, he won't have any files in his AppData location. I could detect that there are no files and create files with default parameters at this location. Would that be a good idea ?
--> The location C:/Users/alecs26/AppData/Roaming/testPaths seems to be classic. Is there a way to get this path without managing all the list of 4 locations ?Thank you very much for your help !
Alex
-
@alecs26 You want your users to be able to change the settings and share them with others at the same time? That would mean that if user A changes something it will affect user B as well - I'm not sure user B will be happy :-)
What you could do: store these files in C:\ProgramData\Mysoft. As soon as a user changes something in your app your app copies these files to C:/Users/USER/AppData/Roaming/MySoft. At start-up the app looks first in C:/Users/USER/AppData/Roaming/MySoft, if no files are there it looks in C:\ProgramData\Mysoft. -
@jsulm Perfect thank you.
Just two questions about this:
1- Just to know, would the user be able to write in the folder C:\ProgramData\Mysoft ?2- What can I do if I want to get this path: C:/Users/USER/AppData/Roaming/MySoft ?
The problem with QStandardPaths::standardLocations(QStandardPaths::AppDataLocation) is that I receive 4 paths. It does not seem robust to just take one of these...For instance, I could do:
QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).at(0);
But maybe in another Windows version or another computer the at(0) location will be another location than what I want... -
However, from what I understand, this is a read-only location ?
It is read-only from design point of view. Whether or not you can actually write to it you need to check at runtime (using QFile interface).
The location C:/Users/alecs26/AppData/Roaming/testPaths seems to be classic. Is there a way to get this path without managing all the list of 4 locations ?
Yes, this location should be returned by
QStandardPaths::writableLocation()
. Just keep in mind this is a location specific to current user. It's not meant to be shared.at(0);
Don't do that. That's relying on implementation details and breaks the documented contract.
-
@Chris-Kawa
Thank you, I did this: qDebug() << QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
and it works : C:/Users/allec74/AppData/Roaming/MySoftHowever, is it possible that in some version of windows or new version of Qt that this function returns a list of location instead of just one location ?
-
@alecs26 said in Get common AppData folder:
However, is it possible that in some version of windows or new version of Qt that this function returns a list of location instead of just one location ?
Unlike
standardLocations
thewritableLocation
method returns a single string, not a list, so no, it will always return single location. If future Qt version provided a list of locations a new function would be introduced that returnedQStringList
. -
Thanks !