I am deploying a product that contains encrypted fields in some config xml files. During installation, I am creating a Self-Signed Certificate on the target machine. Then I use it to encrypt some strings and finally I need to store those in a config file.
In order to create the Certificate I am bringing makecert.exe with me to the target installation directory. So, I need to wait until all files are copied to their destination before I can run my CustomAction which creates the Certificate. After this some other CustomAction is creating the encrypted values that need to be stored in the configs.
This works great, but at this point I would like to store the new values in my config files, but I have already missed the stage at which XmlFile/XmlConfig were executed. In the MSI log I see that the "ExecXmlConfig" action is performed right after the files are copied:
MSI (s) (6C:CC) [02:12:10:898]: Source for file 'makecert.exe' is compressed
InstallFiles: File: makecert.exe, Directory: C:\Program Files (x86)\MyProduct\InstanceFolder\, Size: 60240
MSI (s) (6C:CC) [02:12:10:900]: Executing op: SetTargetFolder(Folder=C:\Program Files (x86)\MyProduct\Nhibernate\)
MSI (s) (6C:CC) [02:12:10:900]: Executing op: SetSourceFolder(Folder=1\o1lebnnf\vemzkq_g\|MyProduct\Nhibernate\)
MSI (s) (6C:CC) [02:12:10:901]: Executing op: FileCopy(SourceName=nw4bpvhi.xml|hibernate.cfg.xml,SourceCabKey=nhibernate.config,DestName=hibernate.cfg.xml,....
MSI (s) (6C:CC) [02:12:10:902]: File: C:\Program Files (x86)\MyProduct\Nhibernate\hibernate.cfg.xml; Won't Overwrite; Won't patch; Existing file is unversioned but modified
MSI (s) (6C:CC) [02:12:10:902]: Executing op: SetTargetFolder(Folder=C:\Program Files (x86)\MyProduct\InstanceFolder\)
MSI (s) (6C:CC) [02:12:10:902]: Executing op: SetSourceFolder(Folder=1\o1lebnnf\|MyProduct\)
MSI (s) (6C:CC) [02:12:10:902]: Executing op: FileCopy(SourceName=7z64.dll,SourceCabKey=Seven7z64.dll,DestName=7z64.dll,Attributes=512,...
MSI (s) (6C:CC) [02:12:10:903]: File: C:\Program Files (x86)\MyProduct\InstanceFolder\7z64.dll; To be installed; Won't patch; No existing file
MSI (s) (6C:CC) [02:12:10:903]: Source for file 'Seven7z64.dll' is compressed
InstallFiles: File: 7z64.dll, Directory: C:\Program Files (x86)\MyProduct\InstanceFolder\, Size: 1484800
MSI (s) (6C:CC) [02:12:10:929]: Executing op: CacheSizeFlush(,)
MSI (s) (6C:CC) [02:12:10:929]: Executing op: ActionStart(Name=ExecXmlConfigRollback,,)
Action 02:12:10: ExecXmlConfigRollback.
MSI (s) (6C:CC) [02:12:10:948]: Executing op: CustomActionSchedule(Action=ExecXmlConfigRollback,ActionType=3329,Source=BinaryData,Target=ExecXmlConfigRollback,...
MSI (s) (6C:CC) [02:12:10:949]: Executing op: ActionStart(Name=ExecXmlConfig,,)
Action 02:12:10: ExecXmlConfig.
MSI (s) (6C:CC) [02:12:10:951]: Executing op: CustomActionSchedule(Action=ExecXmlConfig,ActionType=3073,Source=BinaryData,Target=ExecXmlConfig,CustomActionData=1?C:\Program Files (x86)\MyProduct\Nhibernate\hibernate.cfg.xml?3?0?/hibernate-configuration/session-factory/property[@name='connection.connection_string']????0)
So I'm stuck in between... If I configure my CustomAction to run After='InstallFiles'
it tries to execute long before the files are copied. (am I missing the right event?).
On the other hand, If I configure my Actions to run After='InstallFinalize'
- it's too late, because XmlConfig already fired and didn't write anything to the config file.
Ideally, I would like to run all of this in the very end of the installation.
It seems silly that I should need to write a CustomAction that does exactly the same operation like ExecXmlConfig just to call it at another time...
Here is my InstallExecuteSequence:
<InstallExecuteSequence>
<!-- Create and Register Certificate on Install -->
<Custom Action='GenerateProductCertificate' After='InstallFiles'><![CDATA[REMOVE<>"ALL"]]></Custom>
<Custom Action='RegisterProductServiceCertificate' After='GenerateProductCertificate'><![CDATA[REMOVE<>"ALL"]]></Custom>
<!-- Create and NHibernate Certificate -->
<Custom Action='GenerateNHibernateCertificate' After='RegisterProductServiceCertificate'><![CDATA[REMOVE<>"ALL"]]></Custom>
<!-- Configure NHibernate XML with Encrypted ConnectionString -->
<Custom Action='GenerateSecureConnectionString' After='GenerateNHibernateCertificate'><![CDATA[(REMOVE<>"ALL")]]></Custom>
</InstallExecuteSequence>
I am using WiX 3.7 (v3.7.1022.0, Monday, October 22, 2012)
My Questions are:
- Is there some way to re-schedule the ExecXmlConfig action to run after my CustomActions?
- If not, can I schedule my CustomActions to run between copying the file and ExceXmlConfig?
EDIT:
After a few more attempts and little more research I can define my problem more accurately. What I want to find out is: How to set an Output Value from a Deferred Action that will be available to the next Deferred Action?
My scenario forces me to run my Custom Actions in deferred mode, so I cannot access the Session to store any new Variables. But I am sure that more deferred actions are scheduled, so what I am trying to do is find a way to pass some variables to them.
GenerateSecureConnectionString
needs to return the new ConnectionString into some Property which I want to pass on to XmlConfig to store in the config file. But deferred actions can't access the Session - so eventually it doesn't solve my problem... – Roman