How to set folder permission, in a msi-package, by calling on cacls.exe with a custom action

Posted on 2009-04-12
Medium Priority
Last Modified: 2013-11-14
I am a new user to Installshield and I am trying to modify an allready existing msi-package so that it grants adequate folder permissions for non-administrotr users.

I have been reading every post on the matter on InstallShield own supportforum, and everybody seem to agree that the best way of doing this is by making a custom action which calls on the DOS availible "cacls.exe" or "icacls.exe" command (located in system32 folder). Using cacls is supposed to work alot better than using the "LockPermission table" - which I have also tried to use, without any success.

Using cacls is supposed to be fairly simple. How ever no one seems to be willing to explain in a thorough way, how this is exactly is achieved. This is the command I want to use, which should grant everyone full rights on the folder and its subfolders.

icacls "C:\Program Files (x86)\program_name" /grant:r <user>:(OI)(CI)M /T /C

But since the end-users have the ability to change installation directory I would need to be able to use some kind of a environment variable that can be used in cooperation with the msi-installation. For example:

icacls "C:\[INSTALLDIR]\program_name" /grant:r <user>:(OI)(CI)M /T /C

Some people mention that they use "LaunchAppAndWait when they call for cacls, but beeing the newbie as I am, that doesnt tell me anything. Perhaps you can explain that?

I would be immensely grateful if some one could explain how this can be done, step by step, in InstallShield!
Question by:andre_st
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 3
LVL 40

Expert Comment

by:Vadim Rapp
ID: 24127674
> on InstallShield own supportforum, and everybody seem to agree that the best way of doing this is by making a custom action

Installshield-related public for some reason loves making custom action on every opportunity. Probably that's why practically every major installation made by Installshield soon gets accompanied by "cleanup utility" in order to clean up the mess left behind.

Custom actions generally should be used _only_ when it's absolutely proven that the task can't be accomplished by standard ways. Custom action by definition can't be best way, it is never better than unavoidable evil.

Here are some of the reasons why this is so:
1. if installation fails, everything that Installer have made by standard ways is rolled back. Custom actions of course are not.
2. There are many installation scenarios besides pure and simple loca installation. The product can be advertised; the product can be installed-on-demand; the user profile can be roaming; the product can be installed per-machine or per-user; the product can be repaired; and more. Native Installer actions are all tested and proven to work in each. Custom actions are not, you simply place it in the script, and then suddenly the product won't uninstall because it hits some scenario you did not even know exists, and your action runs where it should not, and fails, failing the whole process.

What exactly did not work with the standard way? by the way, you mentioned the table lockpermissions; why going directly to the table if you can simply right-click your folder in the "destination computer's folders" panel, select Properties/Permissions... and specify the permissions in user-friendly dialog?

I'm also curious how you are going to specify the user to assign permissions to, and generally, why is this necessary. Usually, if you use standard ways to build the installation, the permissions on the folders and files are assigned in exactly the right way, following best practices; unless this application has some very specific and unusual requirements  (whichmost likely would be the consequence of not following best practices in developing the application itself), this area never requires and special attention.

Now that you've been warned...

The way you have posted it should be working - if you insert [PROPERTY], it gets replaced by the property value at the time of installation.

In order to create custom action, click "custom actions and sequences" in the left tree, then right-click Custom Actions in the middle pane and create new action - new EXE - "path referencing a directory".

Author Comment

ID: 24128729
Thank for your detailed answer!

The reason why I need to set permissions in the msi-packet is because the program developer didnt do it right from the beginning. The program stores profile information in the program folder, and therefore the users have to have read/write/change permissions in the programfolder. The program is no longer supported by the developer, so therefore I want to fix this problem in the msi-packet instead.

CACLS/ICACLS: The reason why many people use cacls.exe instead is because using the "lockpermission table" is for some reason ofen unreliable, and simply doesnt work always (either by going straight to the table, or by selecting properties/permission in the destination computer´s folder). I have tried it many times, but nothing seems to happen. The installation runs smoothly, but the permissions are not applied. In the "domain field" I used, among another things, [%USERDOMAIN] as suggested in the InstallShield help, and the usergroup "everyone". I read many posts where people were having problem of getting it working - and they finally solved the problem by calling "cacls" or something similar during install to set permissions. Another reason people mention why cacls should be used instead, is because there is a risk that the "lockpermission" table applies only the permissions in the msi-packet to the folders, and erases others.
I.E other accounts, on the installed machine/domain loose permissions, such as "administrator", "system".

Yet another reason, and a very significant one, is that using "lockpermission" table does not enable you to assign inherited permission. So if you have, lets say 50 folders who also have subfolders - you would have to right click on everyone of them and assign the permissions. That is very time consuming, but this is not a problem when cacls is used.

I´ve been testing some more this morning and I think I am on the right track, regarding "cacls". I created a custom action, in the way you suggested. I read that the script has to be set to "Deferred Execution". I have also read in a forum that the script is preferrably to be executed "after create folders" in the sequence. This way the permissions are applied during the filecopy, instead of in the end of the sequence - therefore saving time. Do you have any comments on this? Would you do this in some other way?

In the "Filename & Command line"-field of the Custom action tab I can write the full pathname of the folders which are to be modified. For example:

cacls.exe "C:\program files\company\programname" /T /E /G everyone:f

And this works well, the permissions are set during install. But I am having a hard time trying to find a way of using the parameter [INSTALLDIR] to work. Since the end-user can choose to install to a different location, I have to, of course, make this work regardless of which directory is beeing used.

How should this be typed in?

Most preferreably I woul like to just use:

cacls.exe "[INSTALLDIR]" /T /E /G everyone:f

But that doesnt work. I have tried other variants like:

c:\program files\[INSTALLDIR]

Thanks again for your help!


LVL 40

Expert Comment

by:Vadim Rapp
ID: 24129189
I have to say, I did not ever try to control the permissions myself, so it's all general suggestions.

cacls.exe "[INSTALLDIR]" /T /E /G everyone:f

should work, but not in deferred execution. Place it in immediate execution; I would place it after CreateFolders, so the files would inherit. You can debug it by specifying instead something like

command.exe /c echo [INSTALLDIR]

so it spawns a message and you see what has been passed.
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

LVL 40

Expert Comment

by:Vadim Rapp
ID: 24129439
Another thought: I think you can resolve your problem more easily and reliably by placing product directory under %appdata% instead of %programfiles%, so it becomes user-writeable without any special effort.

Author Comment

ID: 24130988
I have managed to pinpoint where the problems seems to be. When I looked at the msi-logfiles I noticed that the internal script is indeed reading the correct values of the [INSTALLDIR] Property. The problem is however that the script writes an "\" after the path. For example:

cacls.exe "c:\program files\company\program_name\ /T /E /G everyone:F

And to me, a newbie, this looks fine...but this "\" in the end of the path, makes the "cacls" malfunction. I cannot either use the command line above in CMD. But I can however use:

cacls.exe "c:\program files\company\program_name /T /E /G everyone:F

The question then becomes, how do I go about making InstallShield not adding the "\" at the end of the path? Or is there some other way of solving this?
LVL 40

Expert Comment

by:Vadim Rapp
ID: 24168656
Write vbscript that will remove the backslash and call the cacls.exe. Vbscript can get the value of INSTALLDIR as passed parameter, or as Session.Property("INSTALLDIR")

Author Comment

ID: 24184497
Unfortunately, I do not have the skills required for writing a script like that. That is a bit above my league...

I however found a "partial" solution.

If [INSTALLDIR] points to lets say: "c:\test"

And If I use a wildcard "*" after [INSTALLDIR], like this: "cacls.exe [INSTALLDIR]* /T /E /C /G" it would result in the msi-installer reading it like [INSTALLDIR] as: "c:\test\*"

In this way the msi-installer applies permissions to all files and folders beneath c:\test. This has worked for some of the application I am working with. But this does not actually give permission on the "c:\test" folder itself - only its files and subfolders. So if the program for example needs to create a new file in the c:\test folder - it will not succeed.

LVL 40

Accepted Solution

Vadim Rapp earned 1500 total points
ID: 24184592
> Unfortunately, I do not have the skills required for writing a script like that

p = Session.Property("INSTALLDIR")
if right(p,1) = "\" then p = left(p,len(p)-1)
createobject("wscript.shell").run "cacls.exe """ & p & """ /T /E /C /G"
LVL 13

Expert Comment

ID: 26487283
In case anyone trips over this question like I did, my solution was to use the following.  I was packaging eclipse and INSTALLDIR was going to C:\Program Files\eclipse

An 'Execute Program from destination' action with the following command line:

CACLS "[%ProgramFiles]\eclipse" /e /p Users:C

placed in Deferred Execution / System Context straight after CreateFolders in the Normal Execute sequence.

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

One of the major drawbacks of deploying applications by GPO is the complete lack of any centralized reporting. After a normal deployment, there are two ways to find out if it was successful – by looking in the event log, and by looking in the log of…
If you don't know how to downgrade, my instructions below should be helpful.
Have you created a query with information for a calendar? ... and then, abra-cadabra, the calendar is done?! I am going to show you how to make that happen. Visualize your data!  ... really see it To use the code to create a calendar from a q…
In this video, Percona Director of Solution Engineering Jon Tobin discusses the function and features of Percona Server for MongoDB. How Percona can help Percona can help you determine if Percona Server for MongoDB is the right solution for …

801 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question