WiX: Passing Install path to managed custom action
Solution 1
If you delineate your data like ...
<CustomAction Id="MyCustomActionData" Return="check" Property="MyCustomAction" Value='PROPERTY0=[PROPERTY0];PROPERTY1=[PROPERTY1];PROPERTY2=[PROPERTY2]' Execute='immediate' />
You can access the data like:
string property0 = session.CustomActionData["Property0"];
string property1 = session.CustomActionData["Property1"];
string property2 = session.CustomActionData["Property2"];
In the previous example you would use:
<CustomAction Id="RegisterDflHelp.SetProperty" Return="check" Property="RegisterDflHelp" Value='INSTALLLOCATION=[INSTALLLOCATION]' Execute='immediate' />
then
string cad = session.CustomActionData["INSTALLLOCATION"];
Solution 2
I accomplished this using the following in the .WXS file:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder" Name="PFiles">
<Directory Id="ManufacturerDir" Name="Company" ShortName="Company">
<Directory Id="INSTALLDIR" Name="TheApp">
<Directory Id="BatchFileLocation" Name="BatchFiles">
<Component Id="BatchFilesComp" ... >
<File Id="SomeFile_BAT" Source="BatchFiles\SomeFile.bat" Name="SomeFile.bat" ... />
</Component>
</Directory>
</Directory>
</Directory>
</Directory>
</Directory>
And in the custom Action:
var batchDirectory = session.GetTargetPath("BatchFileLocation");
var batchFile = batchDirectory + "SomeFile.bat"
Now, I haven't yet figured out how to avoid the duplication of the filename, but this does successfully return where the batch file was installed.
Solution 3
After several hours of struglling, the following worked for me:
string UserDefinedInstallDir = session["INSTALLDIR"];
Hope it helps somenone else!
Solution 4
Your passing the value correctly but try this way to reference it.
string[] keys = new string[session.CustomActionData.Keys.Count];
session.CustomActionData.Keys.CopyTo(keys, 0);
string cad = keys[0];
This should set cad
to the installation path like you want it.
Solution 5
Have you tried querying the INSTALLLOCATION property directly from within the managed CA?
string cad = session["INSTALLLOCATION"];
One of the beauties of using DTF is that you have read/write access to all the MSI properties without having to use command-lines etc. So even if INSTALLLOCATION cannot be queried like a normal property you could define your own MSI property set it to the value of INSTALLOCATION and query that one inside your CA instead.
Admin
Updated on August 04, 2020Comments
-
Admin over 3 years
new Day, new Problem;-) Still got to struggle with managed custom action. I already managed it to call an custom action and passing some test data to it. Now I want to replace the testdata with the real data i need. And here the problems starts: I want to call a batch file which was installed in a subdirectory of my installation. Therefore i need to pass the installation path to the custom action. Afaik this can be done using the customactiondata mechanism. But this does not work. When I log the installation I can see that outside of the customaction INSTALLLOCATION is pointing to the correct path, but as soon as i look in the customaction the customactiondata property is empty...
What am I doing wrong?
Merge Module which calls the custom action:
<Module Id="DflHelpInstaller" Language="1033" Version="1.0.0.0"> <Package Id="f952de58-1dc6-46b3-872a-7a49e2d9ea0a" Manufacturer="DflHelpInstaller" InstallerVersion="200" /> <Binary Id='RegisterDflHelpDll' SourceFile="$(var.REGISTERHELP.TargetDir)RegisterDflHelp.CA.dll" /> <CustomAction Id='RegisterDflHelp' BinaryKey='RegisterDflHelpDll' DllEntry='RegisterDflHelp' Execute='deferred' /> <CustomAction Id="RegisterDflHelp.SetProperty" Return="check" Property="RegisterDflHelp" Value='[INSTALLLOCATION]' Execute='immediate' /> <InstallExecuteSequence> <Custom Action='RegisterDflHelp.SetProperty' After='CostFinalize' /> <Custom Action='RegisterDflHelp' After='InstallFiles' /> </InstallExecuteSequence> <Directory Id="TARGETDIR" Name="SourceDir"> </Directory> <ComponentGroupRef Id="HelpGroup"/> </Module> </Wix>
Outline of the installer Project which use the MergeModule:
....
<Directory Id="TARGETDIR" Name="SourceDir"> <Directory Id="ProgramFilesFolder" SourceName="PFFiles"> <Directory Id="Company" Name='$(var.COMPANY)'> <Directory Id="INSTALLLOCATION" SourceName='$var.v[SDK_VERSION]'> <Component Id="MyBanner" Guid="C8C28B92-9326-4991-BFB1-BBDFDF3653AB"> <File Id ="Banner.bmp" Source="Banner.bmp" KeyPath="yes" DiskId="1"/> </Component> <Merge Id ="DflHelpInstaller" SourceFile="DflHelpInstaller.msm" Language="1033" DiskId="1" /> </Directory> </Directory>
....
<Feature Id="Complete" Title="Setup" Description="Installs the SDK on your local machine." Display="expand" Level="1" ConfigurableDirectory="INSTALLLOCATION"> <ComponentRef Id="Banner" /> <ComponentRef Id ="UNINSTALLER"/> <ComponentGroupRef Id="ReferenceGroup"/> <MergeRef Id="DflHelpInstaller"/> </Feature>
CustomAction:
public class CustomActions { [CustomAction] public static ActionResult RegisterDflHelp(Session session) { session.Log("Begin CustomAction1"); session.Log("Before Access to customactiondata"); //should contain the installation path - unfortunately it is empty! why? string cad = session["CustomActionData"]; Debugger.Break(); RegisterHelp(cad); session.Log("End of custom action.."); return ActionResult.Success; }