As a part of service installer using Wix 3.XX, we have been trying to encrypt the connection string. After visiting couple of option on Stackoverflow and some other communities, we have opted to do it in three parts.
- Installer that installs the service in the first part
- At the end of installation it invokes the small executable that picks the location of connection of existing config, encrypts the connection string inside the installation folder and save that config.
- A
.bat
file that clears out the executable for the encryption (basically leaving no traces behind)
All three parts works well with co-ordination, but the encryption executable fails when I try to install that in "Program Files" or "Program Files (x86)" using non-elevated permission (non-admin mode).
Debugging that has given me traces which means that Installer is unauthorized for any such processes.
Here is the code snippet that does it:
1. var fileMap = new ExeConfigurationFileMap { ExeConfigFilename = configPath };
2. var configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
3. var section = configuration.GetSection(sectionToEncrypt);
4. section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
5. section.SectionInformation.ForceSave = true;
6. configuration.Save(ConfigurationSaveMode.Modified);
Reaching at line 6 it returns me with an error:
System.Configuration.ConfigurationErrorsException
HResult=0x80131902
Inner Exception 1:
UnauthorizedAccessException:
Access to the path 'C:\Program Files (x86)\<AppDirectory>\5tkbxj1v.tmp' is denied.
Any inputs for this will be gracious.
Thanks in advance for the help!
Only the sub-section of the
InstallExecuteSequence
betweenInstallInitialize
andInstallFinalize
runs elevated. The rest of the setup has normal user rights, unless the whole MSI has been launched from an already elevatedcmd.exe
prompt.Standard actions in the MSI run elevated, but with regards to custom actions only deferred mode custom actions running without impersonation run in system context with elevated rights. They can only exist between InstallInitialize and InstallFinalize.
It is a very common error to insert immediate mode custom actions after InstallFinalize that try to "tweak" the system in "privileged locations". This will always fail in secure environments or when the setup is run without full admin rights. Even if you set the ACL for the file in question to be writable by standard users, it tends to fail during corporate deployment for several very technical reasons.
Are you retrieving the connection string from the user in the GUI? You should be able to encrypt the data retrieved from the user with a DLL custom action in immediate mode, and then use a deferred mode custom action to write to the config file - when you have elevated rights. Not at all trivial, but possible.
Please provide some comments so we know a bit more about what you are doing, and I will see if I can find a good link for deferred mode custom actions.
Some Relevant Links:
At the risk of repeating some other answers:
You must be running elevated to modify or create data in the Program Files folder. There's nothing new about this, but obviously it means that your program is not elevated. It will run elevated only if marked as deferred.
In your step 3 there is usually no need to use a bat file to clean up your residual program. You can run it as a custom action from the Binary table, so Windows will stream it out, run it, and clean up after you. Note that if you installed that executable as a file and remove it, then you should assume that a repair or upgrade will want the original MSI to re-install it. As a test, remove that file, then repair the product and see if the file is restored.
As a sanity check you should post your WiX source related to the custom action and where it is called. As is often the case, the issue is not the code but it is the environment it is running in.
If the problem is actually caused by the small executable being running in non-admin mode, you can address it by setting
requestedExecutionLevel
asrequireAdministrator
in its application manifest (app.manifest).Here is a step-by-step example.
When the installer launches the executable, a UAC prompt is displayed and user can input a valid admin credential to evaluate the process's privilege.
Files in Program Files folder shouldn't be modified, if your configuration files can't be static for all installations you should put them in other folder like AppData