Not possible to pass WixBundleProviderKey variable to msipackage - wix

I have a problem with the burn built-in variable WixBundleProviderKey. I need to pass the value of this variable to an msi package. My problem is that the value of this variable is not evaluated, and the msi will only receive an empty string. I have tested with other built in variable and it works as expected.
Any ideas why this is not working? Is there a workaround?
Example:
<Fragment>
<PackageGroup Id="Test" >
<MsiPackage Id="Test"
DisplayName="Test 4.10.0002"
DisplayInternalUI="no"
Visible="no"
SourceFile=".\Template\ProductsToInstall\Test\Test 4.10.msi"
Name="Test\Test 4.10.msi"
Cache="yes"
CacheId="Test 4.10"
Compressed="no"
Vital="yes"
Permanent="no">
<MsiProperty Name="BURN_WIXBUNDLEORIGINALSOURCE" Value="[WixBundleOriginalSource]" />
<MsiProperty Name="BURN_COMMONAPPDATAFOLDER" Value="[CommonAppDataFolder]" />
<MsiProperty Name="BURN_WIXBUNDLEPROVIDERKEY" Value="[WixBundleProviderKey]" />
</MsiPackage>
</PackageGroup>
</Fragment>
Thanks in advance

This is a bug that should be fixed in v3.10: http://wixtoolset.org/issues/4630/

Try this trick.
You can create new variable with name "BUNDLE_KEY" (for example)
<Variable Name="BUNDLE_KEY" Type="string" Value="[WixBundleProviderKey]" />
And then apply this variable to MsiProperty:
<MsiProperty Name="YOU_PROPERTY_IN_MSI" Value="[BUNDLE_KEY]" />
I hope it will help you.

Not exactly the answer to the question, but maybe it helps.
In my case I needed to pass the value of WixBundleProviderKey variable to msi to get the full path to my BundeSetup.exe, which is cached in "CommonAppDataFolder\Package Cache\WixBundleProviderKey" directory. To do that I created a property with FileSearch element in msi, providing to the full path of the searching file.
<Property Id="BUNDLECACHEPATH">
<DirectorySearch Id="BundleDirSearch" Path="[CommonAppDataFolder]Package Cache" Depth="1">
<FileSearch Name="BundleSetup.exe" />
</DirectorySearch>
</Property>

Seems like the only way to pass WixBundleProviderKey value in Standard Bootstrapper Application is to pass it through InstallFolder variable:
<Variable Name="InstallFolder" Value="[WixBundleProviderKey]" />
The other solution is to pass it inside the path to the bundle setup temp files through DirectorySearch element variable:
<util:DirectorySearch Path="[TempFolder][WixBundleProviderKey]" Variable="KeyPath" />
<MsiProperty Name="BUNDLE_KEY" Value="[KeyPath]" />
The way to get WixBundleProviderKey in your msi from [BUNDE_KEY] property value is to implement C# Custom Action using String.Substring() method. And put it inside InstallUISequence before AppSearch event - if you want to use the obtained value inside RegistrySearch element.

Related

How to pass AddLocal-Parameter from wix standard bootstrapper to a MsiPackage

With WIX Tools v3.10 I used to add a variable AddLocal to the bundle which I passed to the MsiProperty with the Name="ADDLOCAL" as described by BryanJ in "Pass parameters from bootstrapper to msi bundle package".
<Bundle>
...
<Variable Name="InstallLevel" Type="numeric" bal:Overridable="yes" Value="1"/>
<Variable Name="AddLocal" Type="string" bal:Overridable="yes" Value=""/>
<Chain>
<MsiPackage Id="Addin64bit_loc" Vital="yes" DisplayInternalUI="yes" ...
EnableFeatureSelection="yes" >
...
<MsiProperty Name="INSTALLLEVEL" Value="[InstallLevel]"/>
<MsiProperty Name="ADDLOCAL" Value="[AddLocal]"/>
</MsiPackage>
</Chain>
</Bundle>
Now after switching to v3.11 I get this warning which will turn to an error in v4:
Warning CNDL1149: The 'ADDLOCAL' MsiProperty is controlled by the bootstrapper and cannot be authored.
(Illegal properties are: 'ACTION', 'ADDLOCAL', 'ADDSOURCE', 'ADDDEFAULT', 'ADVERTISE', 'ALLUSERS', 'REBOOT', 'REINSTALL', 'REINSTALLMODE', or 'REMOVE'.)
Remove the MsiProperty element.
This restriction will be enforced as an error in WiX v4.0.
So what is the adequate way in v3.11 to pass an ADDLOCAL parameter from bootstrapper command line to the Msi?
you can influence on ADDLOCAL parameter in your custom bootstrapper project something like that:
_bootstrapper.PlanMsiFeature += (_, ea) =>
{
ea.State = (needToInstall) ? FeatureState.Local : FeatureState.Absent;
};
I ran into the same issue and ended up using a transform with only the ADDLOCAL property set.
Rather than using AddLocal, I found adding code like:
<Feature Id="FeatureB" Level="0">
<Condition Level="1">INSTALL_FEATUREB="1" OR FEATUREB_INSTALLED="1"
</Condition>
</Feature>
to my msi file behaved in a reasonable manner, allowing me to add/remove a feature.
Modified from:
using https://support.firegiant.com/hc/en-us/articles/230912227-Control-feature-states-for-silent-install-
I like using the 'Variable=X' syntax because I find it easier to read. Without the FEATUREB_INSTALLED test I found uninstall did not act as I wanted.
Well, you can always pass a value to a Variable from the Code behind like this.
Bootstrapper.Engine.StringVariables["AddLocal"] = "your value";

Wix SetProperty if Property does not have a value

I have the following code in my WiX installer:
<Property Id="CONFIGPATH" />
<SetProperty Id="CONFIGPATH" After="AppSearch" Value="[INSTALLFOLDER]servers.cfg">NOT CONFIGPATH</SetProperty>
The intention is that the user may pass a custom CONFIGPATH to the installer. If they do not pass a custom path, a default path targetting the installation folder is used. However, this code does not work. SetProperty never fires.
If instead I write:
<Property Id="CONFIGPATH" />
<SetProperty Id="CONFIGPATH" After="AppSearch" Value="[INSTALLFOLDER]servers.cfg"></SetProperty>
The property is updated to (the calculated value of) [INSTALLFOLDER]servers.cfg correctly.
Why might this be?
For some reason, AppSearch is too early in the install sequence. It was necessary to change the code to a later point in the sequence:
<Property Id="CONFIGPATH" />
<SetProperty Id="CONFIGPATH" Sequence="execute"
Before="InstallFiles"
Value="[INSTALLFOLDER]servers.cfg">NOT CONFIGPATH</SetProperty>

Using WiX, how to skip a component when a certain registry key does not exist?

I want to copy some files into a directory in another product's installation tree, but only if that product is installed. So I figured I could set a property based on a registry search to find that product's installation root. Then I could use the property in a condition element on the component element.
Here is my code. For some reason, I am getting an error when the other product is not installed and the registry search comes up empty since the registry key will not be found.
<Property Id="PRODUCTPATH">
<RegistrySearch Id="PRODUCTPATH" Root="HKLM" Key="_MY_KEY_" Name="_MY_NAME_" Type="raw" />
</Property>
<SetProperty Id="PRODUCTBINPATH" Value="[PRODUCTPATH]\BIN" After="AppSearch"/>
<Component Id="CommonDLLs" Guid="_MY_GUID_" Directory="INSTALLLOCATION">
<Condition>PRODUCTPATH</Condition>
<RegistryValue Id="_MY_ID_" Root="HKLM" Key="_MY_KEY_2" Name="Installed" Value="1" Type="integer" KeyPath="yes" />
<CopyFile Id="myfile1.dll" FileId="myfile1.dll" DestinationProperty="PRODUCTPATH" DestinationName="myfile1.dll"/>
<CopyFile Id="myfile2.dll" FileId="myfile2.dll" DestinationProperty="PRODUCTPATH" DestinationName="myfile2.dll"/>
</Component>
Try to use the util:RegistrySearch instead of RegistrySeach
This element comes with Util Extension. Check here if you don't know how to use extensions.
The util:RegistrySearch has an attribute (Result) for only checking if the key exists or not.
It would be like that:
<util:RegistrySearch
Id="PRODUCTPATH"
Variable="PRODUCTPATH"
Root="HKLM"
Key="_MY_KEY_"
Format="raw"
Result="exists">
Actually, all you have to do is add a condition to the SetProperty element like this:
<Property Id="PRODUCTPATH">
<SetProperty Id="PRODUCTBINPATH" Value="[PRODUCTPATH]\BIN" After="AppSearch">PRODUCTPATH</SetProperty>

Passing command line args to MSI from WiX bundle

I’m on Wix 3.7. I have an MSI that I would like to set a registry key (perhaps via a Custom Action, as he will have to check if the key already exists).
I understand that a Bundle in a bootstrapper project can't change the machine state (such as setting the registry). Therefore, I'm attempting to pass a command line argument via <MsiProperty>, but doesn't appear to show up as a command line argument in my log file for the bootstrapper.
Is it possible to set a registry key up in a Bundle?
If not, how can I add a command line argument (or some other piece of custom data)
to be passed to the MSI.
How can the MSI read whatever it is I pass to it (whether It ends up being a command line arg or something
else).
Bundle:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Bundle
Name="MyInstallerBootstrapperLocalDb"
Version="1.0.0.0"
Manufacturer="some company"
UpgradeCode="PUT-GUID-HERE">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense" />
<Chain>
<MsiPackage Id="MyInstallerInstaller"
SourceFile="$(var.MyInstallerInstaller.TargetPath)"
Compressed="no">
<!-- TODO - if this is being set correctly, the MSI needs to
interpret it and set up the key-->
<MsiProperty Name="SetLocalDb" Value="yes"/>
</MsiPackage>
</Chain>
</Bundle>
</Wix>
Your MSI needs to define a property like so:
<Property Id="SOMEPROPERTY" Value="Default"/>
You can then set this property from the bundle:
<MsiPackage SourceFile="<package>.msi" Id="SomeId">
<MsiProperty Name="SOMEPROPERTY" Value="[SomeProperty]" />
</MsiPackage>
After this you can set the property in the Bootstrapper as described here: WiX Bootstrapper: How do I set burn variables from the command line?
Notice that SomeProperty is a Burn variable which you have to define:
<Variable Name="SomeProperty" Type="string" Value="DefaultValue" />
Update:
In the MSI you are then able to do a registry search based on this property:
<RegistrySearch Id="GetSomeValue" Root="HKLM" Key="SOFTWARE\<Manufacturer>\[SOMEPROPERTY]" Name="<ValueName>" Type="raw" />
Just to add an extra bit of information. To alter the variable values with command line, I actually had to set it as overriable.
<Variable Name="SomeProperty" Type="string" Value="true" bal:Overridable="yes" />

Wix CopyFile only on target machine

I need to be able to copy a file that exists on the target machines hard-drive based on a registry setting that holds the folder path.
I have been trying to get this going for a day or two and am having difficulty, can anyone help?
Thanks,
B
Try something along these lines:
<Component Id="MyComponent" Guid="E5FF53DE-1739-42c4-BE37-60F810C9CD69">
<Condition>MYTESTDIR</Condition>
<CopyFile Id="fileToCopy.datCopy" SourceName="[MYTESTDIR]fileToCopy.dat" DestinationProperty="WEBSERVICEBINFOLDER" />
</Component>
You can populate MYTESTDIR with a value from the registry using a RegistrySearch.
You can first search your registry for the file as follows:
<Property Id="PROPERTYNAME" Secure="yes">
<RegistrySearch Id="SomeID"
Root="HKLM"
Type="raw"
Key="SOFTWARE\SomeFolder\SomeSubFolder"
Win64="yes"
Name="InstallPath">
<DirectorySearch Id="REQUIREDDIRECTORY" AssignToProperty="yes" Depth="1" Path="THEEXPECTEDPATH">
</DirectorySearch>
</RegistrySearch>
</Property>
Then use a Custom Action to set the file name
<CustomAction Id="SETFILE"
Property="FILE"
Value="[PROPERTYNAME]file.extension" />
and then copy file as described by the previous answer...
<CopyFile Id="fileToCopy.datCopy" SourceName="[FILE]" DestinationProperty="[YOURDESTINATION]" />