2
votes

If I want to create files in the {commonappdata} folder, I need to add the Permissions:users-modify parameter on a [Files] Source:... line.

This works great ( I finally figured out how to make sure no roaming folder was used when changing one of the installed files from within the installed program ).

However , how can I make INI-entries from the [INI] Filename:... section also writeable by any user on the PC ? There are program values, not user values, after all.

As it is now, the ini-file is written by the Inno-setup installation, but if I later start the installed program and change the ini file grammatically, a roaming version of the ini file is written.

To be complete:

  • I know about the way to create the ini-file as a template when installing your application, and than , upon first run of the program , copy them over to the the {commonappdata} folder, but I am just wondering whether this can be achieved from within the Inno-Setup script.

  • I am running the latest version of Inno-Setup 5.4.2 under Windows 7 Prof 64 ( if this should make a difference ).

2
For reference, this will create a security hole, especially if that file contains paths as it means any random user can make other users open/run/replace files as them.Deanna

2 Answers

2
votes

You'll be blamed for this design. You might have contradicting user settings if you keep them in application data folders. Refer to this question for more blame. ;)

Anyway, only [Files], [Dirs] and [Registry] sections allow 'Permissions' parameter. So it is not possible for an [Ini] section to create an ini file with modified permissions. One way to achieve your task can be to use the 'ini' section to collect necessary information during setup, then as a post-install action, transfer the contents of the ini file to one with modified permissions created through the 'files' section. Something like this:

[Files]
Source: MyProg.ini; DestDir: {commonappdata}\MyCompany; Permissions: users-modify; 
;// ini file contents will be transferred to this file

[Ini]
filename: {commonappdata}\MyCompany\MyProg_Temp.ini; section: users; key: username; string: {username}; Flags: UninsDeleteEntry; 
;// this is used in the installation, and will be deleted in post-install
...

[Code]
procedure CurStepChanged(CurStep: TSetupStep);
var
  s: string;
begin
  if CurStep = ssPostInstall then begin
    if LoadStringFromFile(ExpandConstant('{commonappdata}\MyCompany\MyProg_Temp.ini'), s) and
        SaveStringToFile(ExpandConstant('{commonappdata}\MyCompany\MyProg.ini'), s, False) then
      DeleteFile(ExpandConstant('{commonappdata}\MyCompany\MyProg_Temp.ini'));
  end;
end;
0
votes

Inno Setup allows to set permissions only in sections [Files] [Dirs] and [Registry] and you'll have to use those somehow. Here are 2 solution to this problem. Both are good but each with a slight disadvantage.

Solution #1: Set permission to the entire directory

[Dirs]
Name: {commonappdata}\MyCompany; Permissions:everyone-modify

[INI]
Filename: {commonappdata}\MyCompany\MyProg.ini; Section: "SomeSection"; Key: "SomeKey"; String: "SomeValue"

This is a great solution if you don't mind to have the entire directory's permissions modified. I did mind and came up with a second solution.

Solution #2: Create your .ini file in {tmp} and copy it in the [Files] section:

#define TargetIniDir "{commonappdata}\MyCompany"
#define TargetIniName "MyProg.ini"
....

[Files]
Source: {tmp}\{#TargetIniName}; DestDir: {#TargetIniDir}; Flags:external; Permissions: users-modify;

....

[Code]
procedure PrepareIniFileForCopy(section, key, value, iniFileTemp, iniFileTarget:String);
begin
    if FileExists(iniFileTarget) then 
      FileCopy(iniFileTarget, iniFileTemp, False);

    SetIniString(section, key, value,  iniFileTemp);
end;

procedure CurStepChanged(CurStep: TSetupStep);
var
  iniFile, iniFileTemp:String;
begin
  if CurStep=ssInstall then begin
    PrepareIniFileForCopy('SomeSection', 'SomeKey', 'SomeValue', ExpandConstant('{tmp}\{#TargetIniName}'), ExpandConstant('{#TargetIniDir}\{#TargetIniName}'));

  end;
end;

This will create your .ini file in the {tmp} directory (which will be deleted after install finishes), then copied in the [Files] section to the desired commondata directory with desired permissions. Note the external flag in the [Files] section which means the file isn't packed to the setup at compile time, rather taken dynamically at installation time. Also note that the creation of the temporary file must be done before the install (CurStep=ssInstall means right before installation).

I think this solution is good, but not very pretty. You split your operation to two different places, that rely one one being done before the other.

Both solution can add values to existing .ini files, not just create new ones.