2

I have made an installer (using Inno Setup) for my software, which is finally installed in

C:\Program Files (x86)\MyApp\myapp.exe

as usual on Windows platform, and it works perfectly.

A problem comes when my software tries to write its config file here :

C:\Program Files (x86)\MyApp\myapp.cfg

here a Permission denied error arrives !

The only solution I have found is "Run software as administrator", but I don't like this solution : I don't want to ask the final user to have to do "Run as adminstrator" each time they will use the software.

Is there a clean solution for having the right to write in C:\Program Files (x86)\MyApp\myapp.cfg without asking the final user to "run as administrator" ?

TLama
  • 75,147
  • 17
  • 214
  • 392
Basj
  • 41,386
  • 99
  • 383
  • 673
  • 3
    Yes. There is a solution. Never ever save config files to the application folder! Store it where it should be, in the application data folder. That one will be writable for your app. – TLama Feb 28 '14 at 12:33
  • Thanks @TLama for answer. Do you know a document/tutorial/doc showing what are the good practice about all such things ? Maybe there are some official Microsoft documentation ? Moreover, I'm looking for a solution which works for WinXP, WinVista, Win7, Win8 : do they all have an "application data folder" ? Last question : do you know how to get the "application data folder" path in Python (or any other language) ? – Basj Feb 28 '14 at 12:36
  • I've removed Inno Setup tag from your last two questions since they are not related to the installer itself. – TLama Feb 28 '14 at 23:43
  • Thank you @TLama, you're right. Do you have an idea about the comment below ? http://stackoverflow.com/questions/22095286/writing-config-file-in-c-program-files-x86-myapp-myapp-cfg-vs-administrator?noredirect=1#comment33534403_22095930 ? – Basj Feb 28 '14 at 23:44

1 Answers1

2

As @TLama said, never ever try to write to the application folder. That was never the recommended practice and since Vista Microsoft has disabled it (by first allowing you to write but actually redirecting the writing to another directory, a functionality which in later OS versions seems to have been removed - and good thing too as it was making support hellish).

To retrieve a known folder path, use SHGetFolderPath function. Depending on whether the application data is shared among all users or just used by the user running the app, you should call SHGetFolderPath either with CSIDL_COMMON_APPDATA or with CSIDL_LOCAL_APPDATA respectively. Avoid writing directly in those folders but create subfolders like <your company>\<your app> and use those instead.

Note that SHGetFolderPath has been deprecated and SHGetKnownFolderPath should be used in lieu of it but only if you don't need compatibility with Windows versions prior to Vista.

For completeness sake, this thread also describes how to import SHGetFolderPath into Python.

Update: Corrected to avoid using environment variables and SHGetFolderPath instead per comments by @RemyLebeau @TLama

Community
  • 1
  • 1
ierceg
  • 418
  • 1
  • 8
  • 11
  • Thank you very much. As I want a place that all users can acces, it seems that I have to use `%ALLUSERSPROFILE%\MyApp\myapp.cfg`. This will be `C:\ProgramData\MyApp\myapp.cfg` on WinVista/7 (this looks ok) but `C:\Documents and Settings\All Users\MyApp\myapp.cfg` on WinXP. Is the latter correct ? I don't really remember about WinXP, but I never saw config files in places like `C:\Documents and Settings\All Users\MyApp\myapp.cfg` when I used XP. Is it the **good place** to store config files (for all users) on XP ? – Basj Feb 28 '14 at 13:09
  • 1
    You don't need to care about the physical location of that folder nor hardcode it ever. What you need to do is find that location by the predefined way, which is for Python discussed e.g. in [`this question`](http://stackoverflow.com/q/626796/960757). – TLama Feb 28 '14 at 13:33
  • 1
    I agree with @TLama re not needing to know the right location, just having to ask OS to direct you to the right location. Even for support you don't really want (though I have in the past) to have to tell your users to send you, for example, logs from `C:\Documents and Settings\All Users\MyApp\myapp.log` when on XP or `C:\ProgramData\MyApp\myapp.log` when on Vista or later. These paths can be changed so the only thing you can rely on is OS. Offer the users, from the application itself, to open the application directory for them. – ierceg Feb 28 '14 at 13:40
  • 1
    And yes, using `%ALLUSERPROFILE%\MyApp\myapp.cfg` is a good place to store the config *if you want to share the config between all the users*. – ierceg Feb 28 '14 at 13:41
  • 3
    In code, don't use `%ALLUSERPROFILE%\MyApp`. Use `SHGetFolderPath(CSIDL_COMMON_APPDATA)` or `SHGetKnownFolderPath(FOLDERID_ProgramData)` instead, and then append `\MyApp` to that path. – Remy Lebeau Feb 28 '14 at 18:26
  • Thanks for your comments @RemyLebeau @ierceg @TLama. There is just one thing to solve : on XP, `os.getenv('ALLUSERSPROFILE')` gives `C:\Documents and Settings\All Users` but `SHGetFolderPath(CSIDL_COMMON_APPDATA)` gives `the same + \Application Data` ... What is the good solution ? Example : which one is correct : `C:\Documents and Settings\All Users\MyApp` or `C:\Documents and Settings\All Users\Application Data\MyApp` ? – Basj Feb 28 '14 at 21:52
  • 1
    I've never been friend of environment variables, so I can't tell you what the `ALLUSERSPROFILE` is for, but the `..\Application Data` path returned by the `SHGetFolderPath` is the one I would use. It is described in the [`CSIDL_COMMON_APPDATA`](http://msdn.microsoft.com/en-us/library/windows/desktop/bb762494(v=vs.85).aspx#CSIDL_COMMON_APPDATA) documentation. – TLama Feb 28 '14 at 23:56
  • 2
    Using `%ALLUSERSPROFILE%` is NOT the correct solution in this situation. It gives the path of the shared profile itself, which is NOT the path you are looking for. You are looking for a path WITHIN the shared profile where application data is allowed to be saved. That is what `CSIDL_COMMON_APPDATA` and `FOLDERID_ProgramData` are meant for. So, `C:\Documents and Settings\All Users\Application Data\MyApp` is the correct path, NOT `C:\Documents and Settings\All Users\MyApp`. – Remy Lebeau Mar 01 '14 at 00:26
  • I agree with @RemyLebeau @TLama - `SHGetFolderPath` is the one that you should use and I will edit the answer to reflect this. – ierceg Mar 01 '14 at 23:14